Rollup merge of #56446 - arielb1:special-env-implications, r=nikomatsakis
pass the parameter environment to `traits::find_associated_item` dropping the param-env on the floor is obviously the wrong thing to do. The ICE was probably exposed by #54490 adding the problem-exposing use of `traits::find_associated_item`. Fixes #55380. r? @nikomatsakis
This commit is contained in:
commit
50148a9566
4 changed files with 54 additions and 5 deletions
|
@ -85,6 +85,8 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
source_substs: &'tcx Substs<'tcx>,
|
source_substs: &'tcx Substs<'tcx>,
|
||||||
target_node: specialization_graph::Node)
|
target_node: specialization_graph::Node)
|
||||||
-> &'tcx Substs<'tcx> {
|
-> &'tcx Substs<'tcx> {
|
||||||
|
debug!("translate_substs({:?}, {:?}, {:?}, {:?})",
|
||||||
|
param_env, source_impl, source_substs, target_node);
|
||||||
let source_trait_ref = infcx.tcx
|
let source_trait_ref = infcx.tcx
|
||||||
.impl_trait_ref(source_impl)
|
.impl_trait_ref(source_impl)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -119,10 +121,13 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
/// whichever applies.
|
/// whichever applies.
|
||||||
pub fn find_associated_item<'a, 'tcx>(
|
pub fn find_associated_item<'a, 'tcx>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
item: &ty::AssociatedItem,
|
item: &ty::AssociatedItem,
|
||||||
substs: &'tcx Substs<'tcx>,
|
substs: &'tcx Substs<'tcx>,
|
||||||
impl_data: &super::VtableImplData<'tcx, ()>,
|
impl_data: &super::VtableImplData<'tcx, ()>,
|
||||||
) -> (DefId, &'tcx Substs<'tcx>) {
|
) -> (DefId, &'tcx Substs<'tcx>) {
|
||||||
|
debug!("find_associated_item({:?}, {:?}, {:?}, {:?})",
|
||||||
|
param_env, item, substs, impl_data);
|
||||||
assert!(!substs.needs_infer());
|
assert!(!substs.needs_infer());
|
||||||
|
|
||||||
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
|
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
|
||||||
|
@ -132,7 +137,7 @@ pub fn find_associated_item<'a, 'tcx>(
|
||||||
match ancestors.defs(tcx, item.ident, item.kind, trait_def_id).next() {
|
match ancestors.defs(tcx, item.ident, item.kind, trait_def_id).next() {
|
||||||
Some(node_item) => {
|
Some(node_item) => {
|
||||||
let substs = tcx.infer_ctxt().enter(|infcx| {
|
let substs = tcx.infer_ctxt().enter(|infcx| {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = param_env.with_reveal_all();
|
||||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||||
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
|
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
|
||||||
substs, node_item.node);
|
substs, node_item.node);
|
||||||
|
@ -219,12 +224,17 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
source_trait_ref: ty::TraitRef<'tcx>,
|
source_trait_ref: ty::TraitRef<'tcx>,
|
||||||
target_impl: DefId)
|
target_impl: DefId)
|
||||||
-> Result<&'tcx Substs<'tcx>, ()> {
|
-> Result<&'tcx Substs<'tcx>, ()> {
|
||||||
|
debug!("fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
|
||||||
|
param_env, source_trait_ref, target_impl);
|
||||||
|
|
||||||
let selcx = &mut SelectionContext::new(&infcx);
|
let selcx = &mut SelectionContext::new(&infcx);
|
||||||
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
|
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
|
||||||
let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx,
|
let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx,
|
||||||
param_env,
|
param_env,
|
||||||
target_impl,
|
target_impl,
|
||||||
target_substs);
|
target_substs);
|
||||||
|
debug!("fulfill_implication: target_trait_ref={:?}, obligations={:?}",
|
||||||
|
target_trait_ref, obligations);
|
||||||
|
|
||||||
// do the impls unify? If not, no specialization.
|
// do the impls unify? If not, no specialization.
|
||||||
match infcx.at(&ObligationCause::dummy(), param_env)
|
match infcx.at(&ObligationCause::dummy(), param_env)
|
||||||
|
|
|
@ -33,8 +33,8 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
|
||||||
if ty::tls::with(|tcx| tcx.sess.verbose()) {
|
if ty::tls::with(|tcx| tcx.sess.verbose()) {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Obligation(predicate={:?},cause={:?},depth={})",
|
"Obligation(predicate={:?},cause={:?},param_env={:?},depth={})",
|
||||||
self.predicate, self.cause, self.recursion_depth
|
self.predicate, self.cause, self.param_env, self.recursion_depth
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
write!(
|
write!(
|
||||||
|
|
|
@ -347,9 +347,10 @@ fn resolve_associated_item<'a, 'tcx>(
|
||||||
) -> Option<Instance<'tcx>> {
|
) -> Option<Instance<'tcx>> {
|
||||||
let def_id = trait_item.def_id;
|
let def_id = trait_item.def_id;
|
||||||
debug!("resolve_associated_item(trait_item={:?}, \
|
debug!("resolve_associated_item(trait_item={:?}, \
|
||||||
|
param_env={:?}, \
|
||||||
trait_id={:?}, \
|
trait_id={:?}, \
|
||||||
rcvr_substs={:?})",
|
rcvr_substs={:?})",
|
||||||
def_id, trait_id, rcvr_substs);
|
def_id, param_env, trait_id, rcvr_substs);
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||||
let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
|
let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
|
||||||
|
@ -359,7 +360,7 @@ fn resolve_associated_item<'a, 'tcx>(
|
||||||
match vtbl {
|
match vtbl {
|
||||||
traits::VtableImpl(impl_data) => {
|
traits::VtableImpl(impl_data) => {
|
||||||
let (def_id, substs) = traits::find_associated_item(
|
let (def_id, substs) = traits::find_associated_item(
|
||||||
tcx, trait_item, rcvr_substs, &impl_data);
|
tcx, param_env, trait_item, rcvr_substs, &impl_data);
|
||||||
let substs = tcx.erase_regions(&substs);
|
let substs = tcx.erase_regions(&substs);
|
||||||
Some(ty::Instance::new(def_id, substs))
|
Some(ty::Instance::new(def_id, substs))
|
||||||
}
|
}
|
||||||
|
|
38
src/test/run-pass/issue-55380.rs
Normal file
38
src/test/run-pass/issue-55380.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(specialization)]
|
||||||
|
|
||||||
|
pub trait Foo {
|
||||||
|
fn abc() -> u32;
|
||||||
|
fn def() -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Marker {}
|
||||||
|
|
||||||
|
impl Marker for () {}
|
||||||
|
|
||||||
|
impl<T> Foo for T {
|
||||||
|
default fn abc() -> u32 { 16 }
|
||||||
|
default fn def() -> u32 { 42 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Marker> Foo for T {
|
||||||
|
fn def() -> u32 {
|
||||||
|
Self::abc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(<()>::def(), 16);
|
||||||
|
assert_eq!(<i32>::def(), 42);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue