-
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
Ref suggestion #37658
Ref suggestion #37658
Conversation
r? @Aatch (rust_highfive has picked a reviewer for you, use r? to override) |
r? @nikomatsakis Sub part of #37388. |
5131722
to
8a2215c
Compare
Will this suggest |
@Mark-Simulacrum To me getting the suggestion then, after making that change, an error about the variable not being mutable (with a suggestion to add |
@@ -14,6 +14,5 @@ fn main() { | |||
let _: &[i32] = [0]; | |||
//~^ ERROR mismatched types | |||
//~| expected type `&[i32]` | |||
//~| found type `[{integer}; 1]` |
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.
isn't this a regression in error reporting?
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 have absolutely no clue from where this change comes since my code just added suggestion.
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.
It's probably a stray side-effect? Try wrapping in probe
if you haven't already. In fact, you probably want a version of try_coerce
with no side-effects (call it probe_coerce
).
src/librustc_typeck/check/demand.rs
Outdated
let suggestions = self.check_ref(expr, checked_ty, expected); | ||
let mut err = self.report_mismatched_types(origin, expected, expr_ty, e); | ||
if let Some(suggestions) = suggestions { | ||
err.help(&suggestions); |
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.
why not report a suggestion
instead of a help
?
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.
Indeed!
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.
Apparently, such a thing doesn't exist. (Or at least I didn't find it...).
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.
It's called span_suggestion
: http://manishearth.github.io/rust-internals-docs/rustc/?search=fn%3A%20suggestion
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 was looking for .suggest... You bet I didn't find it haha.
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.
There is a span_suggestion
method on DiagnosticBuilder
:
/// Prints out a message with a suggested edit of the code.
///
/// See `diagnostic::RenderSpan::Suggestion` for more information.
pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
sp: S,
msg: &str,
suggestion: String)
-> &mut Self {
I think the idea is that you replace the given span with the text suggestion
, and also display the help message msg
. Something like:
err.span_suggestion(span, "consider using the `&` operator", format!("&{}", span_to_string(span))
5e858bf
to
af793af
Compare
@nikomatsakis: So, with the current code, it panics it certain cases. Here is the stack trace: https://gist.github.com/GuillaumeGomez/097fec3b6ac4257419fdf100115535f8 @eddyb: proposed a few things:
However he said to consult you first. Any opinion/direction to give me? :-/ |
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.
@GuillaumeGomez sorry for the delayed review, thanks for breaking this out into a separate PR! I'd say it's close, but for a few concerns:
- Can you change to use
span_suggestion
? - Also, can you create
ui
tests instead ofcompile-fail
tests for those cases where you are showing off what your error message does? - I'd like to get to the bottom of the unexpected changes as well; I think that coercion may be registering trait obligations or something like that? (But this is supposed to result in assertion failures, I thought.)
Do you want me to dig into that last point, @GuillaumeGomez?
src/librustc_typeck/check/demand.rs
Outdated
let suggestions = self.check_ref(expr, checked_ty, expected); | ||
let mut err = self.report_mismatched_types(origin, expected, expr_ty, e); | ||
if let Some(suggestions) = suggestions { | ||
err.help(&suggestions); |
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.
There is a span_suggestion
method on DiagnosticBuilder
:
/// Prints out a message with a suggested edit of the code.
///
/// See `diagnostic::RenderSpan::Suggestion` for more information.
pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
sp: S,
msg: &str,
suggestion: String)
-> &mut Self {
I think the idea is that you replace the given span with the text suggestion
, and also display the help message msg
. Something like:
err.span_suggestion(span, "consider using the `&` operator", format!("&{}", span_to_string(span))
Oh, @GuillaumeGomez, just saw your comment, let me process it. |
Yes, ok, those panics are sort of what I expected. =) I'm not sure what is the most elegant fix here. We've been dancing around this problem for a bit. In this particular case, I wonder if we should just add a way to clone the fulfillment context in its entirety, and then just restore it. After all, this is the error path, so performance isn't especially important. This would be like a poor man's persistent data structure. |
Well, performance is important even in case of failure when there are a lot of them (just imagine a code with more than 100 errors in it, it'd be a shame if it took a few seconds to run). Also, considering my very poor background on the rust's internals, I'll need more explanation. |
@nikomatsakis But most of the laziness is already there, shouldn't we do a bit a plumbing instead? |
sorry, didn't get a chance to try out my sample patch today, will do monday
I'm not quite sure what you are thinking here... |
I mean that autoderef already has an obligations list registered late and so does coercion (but only for unsizing). By combining the two we might not even need the ability to register obligations inside a snapshot! |
@eddyb perhaps; I'll have to look into the code in a bit more detail to see what you mean. |
|
||
// Test that we cannot convert from *-ptr to &S and &T (mut version) | ||
let x: *mut S = &mut S; | ||
let y: &S = x; //~ ERROR mismatched types | ||
let y: &T = x; //~ ERROR mismatched types | ||
//~^ ERROR the trait bound `*mut S: T` is not satisfied |
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.
These new cases also don't seem to be reflected by the content of the patch, which doesn't add these errors.
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.
They're fallout from bounds that leak out of a successful coercion attempt.
I've explained in my previous comments a path towards avoiding this side-effect.
It's not obvious what the purpose of this patch is. When adding features, consider explaining in the PR what the feature is and why it is important. |
@brson: I'll, but first I need to remove side-effects and need @nikomatsakis' help. :) |
☔ The latest upstream changes (presumably #37717) made this pull request unmergeable. Please resolve the merge conflicts. |
OK, so, I just pushed a (hacky) commit that removes the side-effects. I'm not sure yet if I'm comfortable landing this or not =) @eddyb, did suggest he thought a cleaner path might be easy to get, and naturally I'd prefer that -- but this seems...not too terrible, for a focused hack. Though it raises the question of how much value these suggestions have in the first place. |
cdea804
to
ab4bdf8
Compare
@nikomatsakis r- on the hack, it does too much for me to be comfortable with it. |
ok, yeah, so on IRC @eddyb elaborated a touch more on what he was thinking (propagating obligations up in a nicer way). Maybe one of us can find time to tinker with it soon. |
Let me know if I can help in any way. |
Ban registering obligations during InferCtxt snapshots. Back in #33852, a flag was added to `InferCtxt` to prevent rolling back a snapshot if obligations were added to some `FulfillmentContext` during the snapshot, to prevent leaking fresh inference variables (created during that snapshot, so their indices would get reused) in obligations, which could ICE or worse. But that isn't enough in the long run, as type-checking ends up relying on success implying that eager side-effects are fine, and while stray obligations *do* get caught nowadays, those errors prevent, e.g. the speculative coercions from #37658, which *have to* be rolled back *even* if they succeed. We can't just allow those obligations to stay around though, because we end up, again, in ICEs or worse. Instead, this PR modifies `lookup_method_in_trait_adjusted` to return `InferOk` containing the obligations that `Autoderef::finalize_as_infer_ok` can propagate to deref coercions. As there shouldn't be *anything* left that registers obligations during snapshots, it's completely banned. r? @nikomatsakis @arielb1
1852221
to
f9a2ac0
Compare
Ok, now I need to fix ui tests. But otherwise seems all good. |
use rustc::infer::type_variable::TypeVariableOrigin; | ||
use rustc::traits::{self, ObligationCause, ObligationCauseCode}; | ||
use rustc::infer::type_variable::{TypeVariableOrigin}; | ||
use rustc::traits::{self, /*FulfillmentContext,*/ ObligationCause, ObligationCauseCode}; |
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.
Comment still here.
/*let saved_fulfillment_cx = | ||
mem::replace( | ||
&mut *self.inh.fulfillment_cx.borrow_mut(), | ||
FulfillmentContext::new());*/ |
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.
Same here. Also not a hack right now.
f9a2ac0
to
1dbd0b4
Compare
Tests passed! \o/ |
@GuillaumeGomez You have comments to remove and a rebase fixup commit to squash. |
1dbd0b4
to
8603060
Compare
Updated. |
@@ -65,7 +65,7 @@ use check::{Diverges, FnCtxt}; | |||
use rustc::hir; | |||
use rustc::hir::def_id::DefId; | |||
use rustc::infer::{Coercion, InferResult, InferOk, TypeTrace}; | |||
use rustc::infer::type_variable::TypeVariableOrigin; | |||
use rustc::infer::type_variable::{TypeVariableOrigin}; |
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.
Heh, leftover edit.
pub fn can_coerce(&self, | ||
expr_ty: Ty<'tcx>, | ||
target: Ty<'tcx>) | ||
-> bool { |
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.
Doesn't this signature fit on one line?
let coerce = Coerce::new(self, cause); | ||
let result = self.probe(|_| coerce.coerce::<hir::Expr>(&[], source, target)).is_ok(); | ||
|
||
result |
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.
Can just have self.probe(...)
as the returned expression.
8603060
to
7ce1eb7
Compare
@bors: r=nikomatsakis,eddyb |
📌 Commit 7ce1eb7 has been approved by |
…komatsakis,eddyb Ref suggestion
…komatsakis,eddyb Ref suggestion
…komatsakis,eddyb Ref suggestion
No description provided.