Skip to content
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

Merged
merged 2 commits into from
Oct 12, 2018

Conversation

matthewjasper
Copy link
Contributor

Also contains a change of span for AscribeUserType.
I'm not quite sure if this was what @nikomatsakis was thinking.

Closes #54620

r? @nikomatsakis

@matthewjasper matthewjasper added the A-NLL Area: Non-lexical lifetimes (NLL) label Oct 9, 2018
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 9, 2018
@@ -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)
Copy link
Contributor

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() {
Copy link
Contributor

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?

Copy link
Contributor

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)

Copy link
Contributor

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() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also here I prefer ?

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:54:02] .................................................................................................... 2200/4578
[00:54:07] ......i............................................................................................. 2300/4578
[00:54:11] .................................................................................................... 2400/4578
[00:54:14] .................................................................................................... 2500/4578
[00:54:18] ...................iiiiiiiii........................................................................ 2600/4578
[00:54:24] .................................................................................................... 2800/4578
[00:54:28] .................................................................................................... 2900/4578
[00:54:31] .......................................i............................................................ 3000/4578
[00:54:34] ...................................................................................................i 3100/4578
---
travis_time:start:test_mir-opt
Check compiletest suite=mir-opt mode=mir-opt (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:07:22] 
[01:07:22] running 47 tests
[01:07:22] ERROR 2018-10-09T23:13:49Z: compiletest::runtest: None
[01:07:41]        AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
[01:07:41]        FakeRead(ForLet, _4);
[01:07:41]        StorageLive(_5);
[01:07:41]        StorageLive(_6);
[01:07:41]        _6 = move _4;
[01:07:41]        replace(_5 <- move _6) -> [return: bb2, unwind: bb5];
[01:07:41] ... (elided)
[01:07:41]    bb2: {
[01:07:41]    bb2: {
[01:07:41]        drop(_6) -> [return: bb6, unwind: bb4];
[01:07:41] ... (elided)
[01:07:41]    bb5: {
[01:07:41]        drop(_6) -> bb4;
[01:07:41]    }
[01:07:41]    }
[01:07:41] Actual:
[01:07:41] fn main() -> (){
[01:07:41]     let mut _0: ();
[01:07:41]     scope 1 {
[01:07:41]         scope 3 {
[01:07:41]             scope 5 {
[01:07:41]                 scope 7 {
[01:07:41]                 scope 8 {
[01:07:41]                 scope 8 {
[01:07:41]                     let _5: std::option::Option<std::boxed::Box<u32>>;
[01:07:41]             }
[01:07:41]             scope 6 {
[01:07:41]             scope 6 {
[01:07:41]                 let _4: std::option::Option<std::boxed::Box<u32>> as Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> };
[01:07:41]         }
[01:07:41]         scope 4 {
[01:07:41]         scope 4 {
[01:07:41]             let _2: bool;
[01:07:41]     }
[01:07:41]     scope 2 {
[01:07:41]     scope 2 {
[01:07:41]         let _1: bool;
[01:07:41]     }
[01:07:41]     let mut _3: bool;
[01:07:41]     let mut _6: std::option::Option<std::boxed::Box<u32>>;
[01:07:41]     bb0: {                              
[01:07:41]         StorageLive(_1);
[01:07:41]         _1 = const fal1:07:41] expected success, got: exit code: 101
[01:07:41] 
[01:07:41] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:07:41] Build completed unsuccessfully in 0:18:27
[01:07:41] Build completed unsuccessfully in 0:18:27
[01:07:41] Makefile:58: recipe for target 'check' failed
[01:07:41] make: *** [check] Error 1

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:26a38a40
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

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 @TimNN. (Feature Requests)

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.
@matthewjasper
Copy link
Contributor Author

Comments addressed and tests fixed

Copy link
Contributor

@nikomatsakis nikomatsakis left a 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
Copy link
Contributor

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.
@matthewjasper
Copy link
Contributor Author

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Oct 10, 2018

📌 Commit c312e04 has been approved by nikomatsakis

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 10, 2018
Copy link
Contributor

@blitzerr blitzerr left a 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(
Copy link
Contributor

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 ?

Copy link
Contributor Author

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,
Copy link
Contributor

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 ?

Copy link
Contributor Author

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.

Copy link
Contributor

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 ?

Copy link
Contributor Author

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)?;
Copy link
Contributor

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 ?

Copy link
Contributor Author

@matthewjasper matthewjasper Oct 12, 2018

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 inT), and the type variable is inferred to be i32`.

Copy link
Contributor

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.

@matthewjasper
Copy link
Contributor Author

matthewjasper commented Oct 12, 2018

What would be the repercussions, if as part of the issue, the only commit was the second commit ?

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.

@bors
Copy link
Contributor

bors commented Oct 12, 2018

⌛ Testing commit c312e04 with merge 2c2e2c5...

bors added a commit that referenced this pull request Oct 12, 2018
[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
@bors
Copy link
Contributor

bors commented Oct 12, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing 2c2e2c5 to master...

@bors bors merged commit c312e04 into rust-lang:master Oct 12, 2018
@matthewjasper matthewjasper deleted the wf-type-annotations branch October 13, 2018 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-NLL Area: Non-lexical lifetimes (NLL) S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants