You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
rustc_typeck::check::compare_method::compare_const_impl doesn't drain its fullfillment context nor invoke regionck. #41323
changed the title [-]rustc_typeck::check::compare_method::compare_const_impl doesn't use its fullfillment context.[/-][+]rustc_typeck::check::compare_method::compare_const_impl doesn't drain its fullfillment context nor invoke regionck.[/+]on May 22, 2017
This is a fairly straight-forward fix, so I'm going to write up some mentoring instructions. Maybe somebody wants to jump in on it!
In general, the code in compare_method.rs is used to compare an associated item definition found in an impl against the trait specification. The name of the file is somewhat outdated; used to be that methods were the only thing where we needed special checks.
I actually suspect that the code for methods and constants could be combined into one function (as this comment suggests), but we can leave that for bonus points.
Let's walk through what the code does now. Imagine we have something like impl<T> Foo<T> for Vec<T> { const X: U = .... Our goal is to check that this type U matches what it says in the trait.
First, we obtain the "trait reference" that the trait is implemented (Foo<T> for Vec<T>, in our example) here and extract its "substs" -- these are the values for the generic paramters of the trait ([Vec<T>, T], as the first thing is the Self parameter).
Next, we load the type of the associated item from the impl (U) here
Then we load the type from the trait here and apply the substitutions from the trait reference. This will substitute Vec<T> for Self and T for the trait's other type parameter, basically.
We then have to normalize those types (remove any associated types we can). You always have to do this after loading types from the HIR currently. Here.
Next we insist that these types are subtypes here and report an error if we get back an error result.
This is where things go wrong. First off, I suspect it'd be better to just require that the types are equal, rather than subtypes. That can be done by changing from sub to eq. But more importantly, the subtype operation works like this:
If it gives back an Error, you get an error, that case is fine.
If it gives back Ok, this does not mean you are done:
It also gives back a series of obligations that you must go and "prove" -- these might be trait requirements or other things. We are processing those obligations by "registering" them with the 'fulfillment context' here, which is good, but we're missing a step later.
Furthermore, there may be various region requirements setup that are being overlooked.
Basically, we've enqueued up a bunch of further checks that we ought to do, but nowhere are we doing them.
We ought to be adding two things (here I am giving links into the method code):
"Selecting" all the obligations that we registered in the fulfillment context. This will check that all the trait obligations are met and so forth. The method code does that here -- this basically means calling select_all_or_error(&infcx).
Performing the "region check" -- the method code does that here. This will do various region checks and then ensure that the region inference can succeed. I think this step is the one that is needed to prevent the example that @withoutboats gave.
In both cases, we should be able to essentially cut-and-paste the existing code.
Activity
nikomatsakis commentedon Apr 20, 2017
triage: P-medium
withoutboats commentedon May 22, 2017
@eddyb does this block stabilization of associated consts?
eddyb commentedon May 22, 2017
@withoutboats Yes, as it allows const types in impls that don't match the trait definition.
withoutboats commentedon May 22, 2017
This can be exploited to elongate lifetimes:
[-]rustc_typeck::check::compare_method::compare_const_impl doesn't use its fullfillment context.[/-][+]rustc_typeck::check::compare_method::compare_const_impl doesn't drain its fullfillment context nor invoke regionck.[/+]aturon commentedon May 22, 2017
I'm renominating, given the exploit that @withoutboats found.
nikomatsakis commentedon May 26, 2017
This is a fairly straight-forward fix, so I'm going to write up some mentoring instructions. Maybe somebody wants to jump in on it!
In general, the code in
compare_method.rsis used to compare an associated item definition found in an impl against the trait specification. The name of the file is somewhat outdated; used to be that methods were the only thing where we needed special checks.I actually suspect that the code for methods and constants could be combined into one function (as this comment suggests), but we can leave that for bonus points.
Let's walk through what the code does now. Imagine we have something like
impl<T> Foo<T> for Vec<T> { const X: U = .... Our goal is to check that this typeUmatches what it says in the trait.Foo<T> for Vec<T>, in our example) here and extract its "substs" -- these are the values for the generic paramters of the trait ([Vec<T>, T], as the first thing is theSelfparameter).U) hereVec<T>forSelfandTfor the trait's other type parameter, basically.This is where things go wrong. First off, I suspect it'd be better to just require that the types are equal, rather than subtypes. That can be done by changing from
subtoeq. But more importantly, the subtype operation works like this:Basically, we've enqueued up a bunch of further checks that we ought to do, but nowhere are we doing them.
We ought to be adding two things (here I am giving links into the method code):
select_all_or_error(&infcx).In both cases, we should be able to essentially cut-and-paste the existing code.
nikomatsakis commentedon May 26, 2017
Tagging as E-mentor.
associated_consts: check trait obligations and regionck for associate…
Rollup merge of rust-lang#42324 - seanmonstar:41323-compare_const_imp…
Rollup merge of rust-lang#42324 - seanmonstar:41323-compare_const_imp…