-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Implement RFC 2056 trivial constraints in where clauses #48557
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @nikomatsakis (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
☔ The latest upstream changes (presumably #48449) made this pull request unmergeable. Please resolve the merge conflicts. |
This is so cool! :) |
Typo. You may want to double check any other places for the same one. |
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.
D'oh! I had this review with a few initial questions for some time but never submitted it! Sorry about that. I've been wondering why you didn't respond ;)
src/librustc/infer/mod.rs
Outdated
@@ -1492,7 +1492,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { | |||
let ty = self.resolve_type_vars_if_possible(&ty); | |||
// Even if the type may have no inference variables, during | |||
// type-checking closure types are in local tables only. | |||
if !self.in_progress_tables.is_some() || !ty.has_closure_types() { | |||
if !self.in_progress_tables.is_some() || !ty.has_closure_types() || param_env.is_global() { |
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 you clarify why you added this param_env.is_global()
check?
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.
Hmm, looks like I added this before I put in the changes to ParamEnv::and
from #48411. It doesn't appear to be needed now.
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.
Ok, let's remove then =)
@@ -518,17 +518,8 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, | |||
|
|||
let predicates: Vec<_> = | |||
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()) | |||
.filter(|p| !p.is_global()) // (*) | |||
.collect(); |
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, can you clarify how you avoid the soundness problems discussed here =)
Is that related to the global check?
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 couldn't create any soundness problems after removing this, so I can't really be sure that I have avoided it. See the tests for an idea of what I attempted.
It looks like the current caching is (at the time of making this PR) very conservative, which probably explains this though.
rust/src/librustc/traits/select.rs
Lines 1271 to 1282 in 3edb3cc
fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool { | |
// If there are any where-clauses in scope, then we always use | |
// a cache local to this particular scope. Otherwise, we | |
// switch to a global cache. We used to try and draw | |
// finer-grained distinctions, but that led to a serious of | |
// annoying and weird bugs like #22019 and #18290. This simple | |
// rule seems to be pretty clearly safe and also still retains | |
// a very high hit rate (~95% when compiling rustc). | |
if !param_env.caller_bounds.is_empty() { | |
return false; | |
} | |
src/librustc/traits/select.rs
Outdated
&& !obligation.param_env.is_global() { | ||
// If a param env has no global bounds, global obligations do not | ||
// depend on its particular value in order to work, so we can clear | ||
// out the param env and get better caching. |
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.
Well, I guess this is part of how we avoid the soundness problems too. I am trying to decide if this is_global
check on the param environment suffices. I think it probably does given the current definitions of elaboration, but won't once we have a better definition of implied bounds (but that will require the newer solver, in which this PR is sort of easier to implement anyway).
I am imagining cases like this:
trait Foo where u32: Bar { }
trait Bar { }
Now, if we were to fully elaborate, T: Foo
would imply u32: Bar
.
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.
Well, I guess this is part of how we avoid the soundness problems too.
Yes, but this only seemed to cause bounds to not apply in my testing.
I am imagining cases like this:
trait Foo where u32: Bar { } trait Bar { }Now, if we were to fully elaborate, T: Foo would imply u32: Bar.
True, but this is surely just as much a problem with fully elaborating
trait Foo where Vec<T>: Copy { } trait Bar { }
src/librustc/traits/select.rs
Outdated
@@ -2074,7 +2071,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { | |||
Where(ty::Binder(Vec::new())) | |||
} | |||
|
|||
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never, | |||
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => None, |
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 interesting. Should we remove Never
from the enum? (Did you do so? If so, I missed it.)
src/librustc/ty/mod.rs
Outdated
ParamEnvAnd { | ||
param_env: self, | ||
value, | ||
match self.reveal { |
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 landed a change much like 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.
That's where it's from. 😄
@matthewjasper so -- much as this PR somehow makes me mildly nervous -- I can't think of a reason this won't work =) I suggest you rebase and remove the WIP comment from the header, so I can r+ ... |
c03bacd
to
b080ee2
Compare
rebased A few further changes:
@nikomatsakis Done, but this still needs a feature gate, right? |
Um, yes, right. I was.. uh.. just testing you to see if you'd remember. |
@matthewjasper let me know when you add feature gate then =) |
760cec8
to
fcfbfe0
Compare
@nikomatsakis Feature gate now added. I haven't feature-gated built-in trait bound errors (e.g. The commits are now a bit of a mess, but I can clean them up later. |
☔ The latest upstream changes (presumably #49264) made this pull request unmergeable. Please resolve the merge conflicts. |
@matthewjasper thanks -- sorry for being slow, will re-review |
8ce2022
to
1c3854a
Compare
src/librustc_typeck/check/wfcheck.rs
Outdated
@@ -683,8 +683,8 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>( | |||
let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); | |||
|
|||
for pred in implied_obligations { | |||
// HAS_LOCAL_NAMES is used to match the existing behvaiour. | |||
if !pred.has_type_flags(ty::TypeFlags::HAS_LOCAL_NAMES) { | |||
// Match the existing behvaior. |
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.
Nit: behavoir
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.
Nit: behavior
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 upon rebase
40eb071
to
ad37f44
Compare
ad37f44
to
be2900c
Compare
rebased. |
@bors r=nikomatsakis |
📌 Commit be2900c has been approved by |
Implement RFC 2056 trivial constraints in where clauses This is an implementation of the new behaviour for #48214. Tests are mostly updated to show the effects of this. Feature gate hasn't been added yet. Some things that are worth noting and are maybe not want we want * `&mut T: Copy` doesn't allow as much as someone might expect because there is often an implicit reborrow. * ~There isn't a check that a where clause is well-formed any more, so `where Vec<str>: Debug` is now allowed (without a `str: Sized` bound).~ r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
Prevent main from having a where clause. Closes #50714 Should this have a crater run? cc #48557, #48214 r? @nikomatsakis
This is an implementation of the new behaviour for #48214. Tests are mostly updated to show the effects of this. Feature gate hasn't been added yet.
Some things that are worth noting and are maybe not want we want
&mut T: Copy
doesn't allow as much as someone might expect because there is often an implicit reborrow.There isn't a check that a where clause is well-formed any more, sowhere Vec<str>: Debug
is now allowed (without astr: Sized
bound).r? @nikomatsakis