-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
[NLL] Check user types are well-formed #54942
Conversation
@@ -90,8 +90,7 @@ pub(super) fn relate_type_and_user_type<'tcx>( | |||
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), | |||
v1, | |||
b_variables, | |||
).relate(&b_value, &a)?; | |||
Ok(()) | |||
).relate(&b_value, &a).map_err(From::from) |
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.
This is indeed not quite what I had in mind. I was imagining something more like this.
let mut relating = TypeRelating::new(...);
relating.relate(&b_value, &a)?;
let canonical_var_values = CanonicalVarValues {
var_values: relating.canonical_var_values
};
Ok(b.substitute(&canonical_var_values))
what this would do is to take the canonical type and replace all the "canonical variables" with the values that we inferred during relate_tys
. It would not require the changes to "propagate back" a correct type. Those make me a bit nervous, as it's not really obvious what to return for a <: b
. And as a case in point, in the case of handling higher-ranked things, we convert a == b
to a <: b
and b <: a
, so which return value should we give back? etc
@@ -482,8 +481,10 @@ where | |||
// Watch out for the case that we are matching a `?T` against the | |||
// right-hand side. | |||
if let ty::Infer(ty::CanonicalTy(var)) = a.sty { | |||
self.relate_var(var, b.into())?; | |||
Ok(a) | |||
self.relate_var(var, b.into()).map(|kind| match kind.unpack() { |
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 would prefer to use ?
here, is there a reason not to?
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 just find it much easier to read)
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.
e.g.,
match self.relate_var(...)?.unpack() {
UnpackedKind::Ty(ty) => Ok(ty),
...
}
@@ -500,8 +501,10 @@ where | |||
b: ty::Region<'tcx>, | |||
) -> RelateResult<'tcx, ty::Region<'tcx>> { | |||
if let ty::ReCanonical(var) = a { | |||
self.relate_var(*var, b.into())?; | |||
return Ok(a); | |||
return self.relate_var(*var, b.into()).map(|kind| match kind.unpack() { |
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.
also here I prefer ?
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
17596a8
to
77b0d1b
Compare
Also change the order of the fake read for let and the AscribeUserType, so that we use the better span and message from the fake read in errors.
77b0d1b
to
8c99712
Compare
Comments addressed and tests fixed |
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.
r=me with a FIXME comment
@@ -49,7 +47,8 @@ fn with_assoc<'a,'b>() { | |||
// outlive 'a. In this case, that means TheType<'b>::TheAssocType, | |||
// which is &'b (), must outlive 'a. | |||
|
|||
let _: &'a WithAssoc<TheType<'b>> = loop { }; //~ ERROR reference has a longer lifetime | |||
let _x: &'a WithAssoc<TheType<'b>> = loop { }; | |||
//~^ ERROR reference has a longer lifetime |
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 we ope an issue regarding enforcing WF conditions in dead code and put a FIXME here like this:
FIXME(#XXX) -- NLL doesn't enforce WF conditions (or any type annotations) in dead code.
Also update some tests so that they don't have user types on `_` in unreachable code.
8c99712
to
c312e04
Compare
@bors r=nikomatsakis |
📌 Commit c312e04 has been approved by |
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.
@matthewjasper
**This is just for the purposes of my understanding :)
Can you explain why this change was required at all? What would be the repercussions, if as part of the issue, the only commit was the second commit ?
@@ -970,15 +970,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { | |||
locations: Locations, | |||
category: ConstraintCategory, | |||
) -> Fallible<()> { | |||
relate_tys::relate_type_and_user_type( | |||
let ty = relate_tys::relate_type_and_user_type( |
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 is okay to have a variable name the same as the module name ?
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.
yes
@@ -85,13 +85,24 @@ pub(super) fn relate_type_and_user_type<'tcx>( | |||
// variance to get the right relationship. | |||
let v1 = ty::Contravariant.xform(v); | |||
|
|||
TypeRelating::new( | |||
let mut type_relating = TypeRelating::new( | |||
infcx.tcx, | |||
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), | |||
v1, | |||
b_variables, |
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.
b_variables
Can you explain to me how this magic happens ? b.variables is written as b_variables ?
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.
b is destructured just above this.
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.
Would you mind pointing me to the line please ?
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.
line 79
).relate(&b_value, &a)?; | ||
Ok(()) | ||
); | ||
type_relating.relate(&b_value, &a)?; |
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.
type_relating.relate(&b_value, &a)?;
Can you explain to me what this line does ?
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 checks that a
and b_value
are the same type apart from lifetimes, if they're not it returns an error to the caller. Otherwise, depending on v1
, it adds any outlives constraints that are required for a
being a subtype of b
, or b
being a subtype of a
or b
being the same type as a
to the borrowck_context
(if it's Some
, which it will be during the NLL type check). Finally it works out what any type variables in b
should be based on a
.
So if b
is &mut '_1 &'_2 _
, a
is &mut '_3 &'_4 i32 and
v1is Covariant, the constraints added are
'_1: '_3,
'_2: '_4and
'_4: '_2(the last constraint comes from
&mut Tbeing invariant in
T), and the type variable is inferred to be
i32`.
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.
@matthewjasper Thanks a lot for the explanation. Really appreciate it.
The first commit is a somewhat unrelated diagnostics change. If it wasn't there then the error messages would point to the variables instead of the type annotation. |
[NLL] Check user types are well-formed Also contains a change of span for AscribeUserType. I'm not quite sure if this was what @nikomatsakis was thinking. Closes #54620 r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
Also contains a change of span for AscribeUserType.
I'm not quite sure if this was what @nikomatsakis was thinking.
Closes #54620
r? @nikomatsakis