Skip to content

Fix ICE involving calling Instance.ty during const evaluation - #67800

Merged
bors merged 7 commits into
rust-lang:masterfrom
Aaron1011:fix/mir-generic-instance
Jan 6, 2020
Merged

Fix ICE involving calling Instance.ty during const evaluation#67800
bors merged 7 commits into
rust-lang:masterfrom
Aaron1011:fix/mir-generic-instance

Conversation

@Aaron1011

Copy link
Copy Markdown
Contributor

Fixes#67639

Instance.ty assumes that we are in a fully monomorphic context (e.g.
codegen), and can therefore use an empty ParamEnv when performing
normalization. Howver, the MIR constant evaluator code ends up calling
Instance.ty as a result of us attemptign to 'speculatively'
const-evaluate generic functions during const propagation.

As a result,
we may end up with projections involving type parameters
(e.g. ::Bar>) in the type we are trying to normalize.
Normalization expects us to have proper predicates in the ParamEnv for
such projections, and will ICE if we don't.

This commit adds a new method Instance.ty_env, which takes a
ParamEnv for use during normalization. The MIR const-evaluator code is
changed to use this method, passing in the proper ParamEnv for the
context at hand.

@rust-highfive

Copy link
Copy Markdown
Contributor

r? @varkor

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfiverust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2020
@Aaron1011Aaron1011 changed the title Fix ICE involving calling Instance.ty durign const evaluationFix ICE involving calling Instance.ty during const evaluationJan 2, 2020
@Aaron1011
Aaron1011force-pushed the fix/mir-generic-instance branch from 51b9fa5 to 1e08f9eCompareJanuary 2, 2020 05:51
@Centril

This comment has been minimized.

@Aaron1011
Aaron1011force-pushed the fix/mir-generic-instance branch from 1e08f9e to 7e86561CompareJanuary 2, 2020 09:46
@Aaron1011

This comment has been minimized.

Comment threadsrc/librustc/ty/instance.rs Outdated
@rust-highfive

Copy link
Copy Markdown
Contributor

The job x86_64-gnu-llvm-7 of your PR failed (pretty log, 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.
2020-01-03T01:39:32.1959938Z ##[command]git remote add origin https://github.com/rust-lang/rust
2020-01-03T01:39:32.7518807Z ##[command]git config gc.auto 0
2020-01-03T01:39:32.7520920Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2020-01-03T01:39:32.7524338Z ##[command]git config --get-all http.proxy
2020-01-03T01:39:32.7527028Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/67800/merge:refs/remotes/pull/67800/merge

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)

Comment threadsrc/librustc/ty/instance.rs Outdated
@wesleywiser

Copy link
Copy Markdown
Member

@bors try

@rust-timer queue

@rust-timer

Copy link
Copy Markdown
Collaborator

Awaiting bors try build completion

@bors

bors commented Jan 3, 2020

Copy link
Copy Markdown
Collaborator

⌛ Trying commit b9dcd9814b4f8b37cfe0b0136cc10ed7797d30eb with merge c8783d8cf524e2ceaad6d300e62e58e68a6d22cf...

@bors

bors commented Jan 3, 2020

Copy link
Copy Markdown
Collaborator

☀️ Try build successful - checks-azure
Build commit: c8783d8cf524e2ceaad6d300e62e58e68a6d22cf (c8783d8cf524e2ceaad6d300e62e58e68a6d22cf)

@rust-timer

Copy link
Copy Markdown
Collaborator

Queued c8783d8cf524e2ceaad6d300e62e58e68a6d22cf with parent 4877e16, future comparison URL.

@Aaron1011

Copy link
Copy Markdown
ContributorAuthor

For some reason, the bot didn't comment saying that benchmarking completed.

It looks like this change had no perf impact above the noise floor, as I had hoped.

@wesleywiserwesleywiser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Code and perf look good to me and the change seems reasonable enough but I don't think I know enough about the resolver to sign off on this myself. Perhaps @oli-obk or someone else could take a look as well?

Comment threadsrc/librustc/ty/instance.rs Outdated
Comment threadsrc/librustc/ty/instance.rs Outdated
Aaron1011and others added 5 commits January 5, 2020 14:37
Fixesrust-lang#67639
`Instance.ty` assumes that we are in a fully monomorphic context (e.g.
codegen), and can therefore use an empty `ParamEnv` when performing
normalization. Howver, the MIR constant evaluator code ends up calling
`Instance.ty` as a result of us attemptign to 'speculatively'
const-evaluate generic functions during const propagation.
As a result,
we may end up with projections involving type parameters
(e.g. <T as MyTrait>::Bar>) in the type we are trying to normalize.
Normalization expects us to have proper predicates in the `ParamEnv` for
such projections, and will ICE if we don't.
This commit adds a new method `Instance.ty_env`, which takes a
`ParamEnv` for use during normalization. The MIR const-evaluator code is
changed to use this method, passing in the proper `ParamEnv` for the
context at hand.
Co-Authored-By: Wesley Wiser <wwiser@gmail.com>
@Aaron1011
Aaron1011force-pushed the fix/mir-generic-instance branch from b9dcd98 to 33caf0bCompareJanuary 5, 2020 20:00
@Aaron1011

Copy link
Copy Markdown
ContributorAuthor

@oli-obk: Updated

Comment threadsrc/librustc_mir/interpret/traits.rs Outdated
// adjustments `FnAbi::of_instance` might be performing.
fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
let ty = self.ty(tcx);
let ty = self.monomorphic_ty(tcx);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's not obvious to me that this is correct. Ca you go up the call chain and see if there are any noncodegen uses?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The only caller is FnAbi:of_instance, which is only called from codegen.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We need to stop assuming that codegen = monomorphic.

@oli-obk

Copy link
Copy Markdown
Contributor

r? @oli-obk

@bors r+

@bors

bors commented Jan 5, 2020

Copy link
Copy Markdown
Collaborator

📌 Commit 336b902 has been approved by oli-obk

@rust-highfiverust-highfive assigned oli-obk and unassigned varkorJan 5, 2020
@borsbors 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 Jan 5, 2020
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jan 6, 2020
… r=oli-obk
Fix ICE involving calling `Instance.ty` during const evaluation
Fixesrust-lang#67639
`Instance.ty` assumes that we are in a fully monomorphic context (e.g.
codegen), and can therefore use an empty `ParamEnv` when performing
normalization. Howver, the MIR constant evaluator code ends up calling
`Instance.ty` as a result of us attemptign to 'speculatively'
const-evaluate generic functions during const propagation.
As a result,
we may end up with projections involving type parameters
(e.g. <T as MyTrait>::Bar>) in the type we are trying to normalize.
Normalization expects us to have proper predicates in the `ParamEnv` for
such projections, and will ICE if we don't.
This commit adds a new method `Instance.ty_env`, which takes a
`ParamEnv` for use during normalization. The MIR const-evaluator code is
changed to use this method, passing in the proper `ParamEnv` for the
context at hand.
bors added a commit that referenced this pull request Jan 6, 2020
Rollup of 6 pull requests
Successful merges:
- #67800 (Fix ICE involving calling `Instance.ty` during const evaluation)
- #67873 (change remove to have a PartialEq bound)
- #67897 (Use `as_deref()` to replace `as_ref().map(...)`)
- #67906 (Silence `TooGeneric` error)
- #67912 (macros: typo fix)
- #67915 (Use Self instead of $type)
Failed merges:
r? @ghost
@bors
bors merged commit 336b902 into rust-lang:masterJan 6, 2020
Comment on lines -65 to +93
pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
/// Returns the `Ty` corresponding to this `Instance`,
/// with generic substitutions applied and lifetimes erased.
///
/// This method can only be called when the 'substs' for this Instance
/// are fully monomorphic (no `ty::Param`'s are present).
/// This is usually the case (e.g. during codegen).
/// However, during constant evaluation, we may want
/// to try to resolve a `Instance` using generic parameters
/// (e.g. when we are attempting to to do const-propagation).
/// In this case, `Instance.ty_env` should be used to provide
/// the `ParamEnv` for our generic context.
pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
// There shouldn't be any params - if there are, then
// Instance.ty_env should have been used to provide the proper
// ParamEnv
if self.substs.has_param_types() {
bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs);
}
tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty)
}

/// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during
/// normalization. This method is only really useful during constant evaluation,
/// where we are dealing with potentially generic types.
pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would keep a single ty method and force callers to pass in ty::ParamEnv::reveal_all() (eventually all of codegen should have to keep track of a ParamEnv anyway, because of @davidtwco's work on partial monomorphization).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-borsStatus: 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.

ICE: could not fully normalize fn with -Z mir-opt-level=3

10 participants

@Aaron1011@rust-highfive@Centril@wesleywiser@rust-timer@bors@oli-obk@eddyb@bjorn3@varkor