-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Fix ICE involving calling Instance.ty
during const evaluation
#67800
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
Changes from all commits
ee922d4
d41f9dd
71d163b
464b58c
33caf0b
db2c4f2
336b902
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,10 +62,35 @@ pub enum InstanceDef<'tcx> { | |
} | ||
|
||
impl<'tcx> Instance<'tcx> { | ||
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) | ||
} | ||
Comment on lines
-65
to
+93
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would keep a single |
||
} | ||
|
||
impl<'tcx> InstanceDef<'tcx> { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2301,7 +2301,7 @@ impl<'tcx> ty::Instance<'tcx> { | |
// or should go through `FnAbi` instead, to avoid losing any | ||
// 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only caller is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to stop assuming that codegen = monomorphic. |
||
match ty.kind { | ||
ty::FnDef(..) | | ||
// Shims currently have type FnPtr. Not sure this should remain. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// compile-flags: -Z mir-opt-level=3 | ||
// build-pass | ||
|
||
// This used to ICE in const-prop due | ||
// to an empty ParamEnv being used during normalization | ||
// of a generic type | ||
|
||
|
||
fn main() { | ||
join_all::<u32>(); | ||
} | ||
|
||
trait Foo { | ||
type Item; | ||
} | ||
|
||
impl Foo for u32 { | ||
type Item = u8; | ||
} | ||
|
||
trait Bar { | ||
type Item2; | ||
} | ||
|
||
impl Bar for u8 { | ||
type Item2 = u64; | ||
} | ||
|
||
fn join_all<I>() | ||
where I: Foo, | ||
I::Item: Bar | ||
{ | ||
Vec::<<I::Item as Bar>::Item2>::new(); // ICE occurs processing this line | ||
} |
Uh oh!
There was an error while loading. Please reload this page.