Skip to content
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

Add support for trait-objects without a principal #56837

Merged
merged 12 commits into from
Jan 5, 2019
1 change: 1 addition & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ define_dep_nodes!( <'tcx>
[] AdtDefOfItem(DefId),
[] ImplTraitRef(DefId),
[] ImplPolarity(DefId),
[] Issue33140SelfTy(DefId),
[] FnSignature(DefId),
[] CoerceUnsizedInfo(DefId),

Expand Down
4 changes: 0 additions & 4 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,10 +337,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
self.infcx.tcx
}

fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.infcx.trait_object_mode()
}

fn tag(&self) -> &'static str {
"Generalizer"
}
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>

fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }

fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}

fn a_is_expected(&self) -> bool { self.a_is_expected }

fn relate_item_substs(&mut self,
Expand Down
6 changes: 1 addition & 5 deletions src/librustc/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::Subtype;

use traits::ObligationCause;
use ty::{self, Ty, TyCtxt};
use ty::relate::{self, Relate, RelateResult, TypeRelation};
use ty::relate::{Relate, RelateResult, TypeRelation};

/// "Greatest lower bound" (common subtype)
pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
Expand All @@ -26,10 +26,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Glb" }

fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}

fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }

fn a_is_expected(&self) -> bool { self.a_is_expected }
Expand Down
6 changes: 1 addition & 5 deletions src/librustc/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::Subtype;

use traits::ObligationCause;
use ty::{self, Ty, TyCtxt};
use ty::relate::{self, Relate, RelateResult, TypeRelation};
use ty::relate::{Relate, RelateResult, TypeRelation};

/// "Least upper bound" (common supertype)
pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
Expand All @@ -26,10 +26,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Lub" }

fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}

fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }

fn a_is_expected(&self) -> bool { self.a_is_expected }
Expand Down
19 changes: 1 addition & 18 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use syntax_pos::{self, Span};
use traits::{self, ObligationCause, PredicateObligations, TraitEngine};
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use ty::fold::TypeFoldable;
use ty::relate::{RelateResult, TraitObjectMode};
use ty::relate::RelateResult;
use ty::subst::{Kind, Substs};
use ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners};
use ty::{FloatVid, IntVid, TyVid};
Expand Down Expand Up @@ -171,9 +171,6 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
// This flag is true while there is an active snapshot.
in_snapshot: Cell<bool>,

// The TraitObjectMode used here,
trait_object_mode: TraitObjectMode,

// A set of constraints that regionck must validate. Each
// constraint has the form `T:'a`, meaning "some type `T` must
// outlive the lifetime 'a". These constraints derive from
Expand Down Expand Up @@ -465,7 +462,6 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
arena: SyncDroplessArena,
interners: Option<CtxtInterners<'tcx>>,
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
trait_object_mode: TraitObjectMode,
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
Expand All @@ -475,7 +471,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
arena: SyncDroplessArena::default(),
interners: None,
fresh_tables: None,
trait_object_mode: TraitObjectMode::NoSquash,
}
}
}
Expand All @@ -488,12 +483,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
self
}

pub fn with_trait_object_mode(mut self, mode: TraitObjectMode) -> Self {
debug!("with_trait_object_mode: setting mode to {:?}", mode);
self.trait_object_mode = mode;
self
}

/// Given a canonical value `C` as a starting point, create an
/// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is
Expand All @@ -520,7 +509,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R {
let InferCtxtBuilder {
global_tcx,
trait_object_mode,
ref arena,
ref mut interners,
ref fresh_tables,
Expand All @@ -532,7 +520,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
f(InferCtxt {
tcx,
in_progress_tables,
trait_object_mode,
projection_cache: Default::default(),
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
int_unification_table: RefCell::new(ut::UnificationTable::new()),
Expand Down Expand Up @@ -614,10 +601,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.in_snapshot.get()
}

pub fn trait_object_mode(&self) -> TraitObjectMode {
self.trait_object_mode
}

pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
}
Expand Down
14 changes: 0 additions & 14 deletions src/librustc/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,13 +372,6 @@ where
self.infcx.tcx
}

fn trait_object_mode(&self) -> relate::TraitObjectMode {
// squashing should only be done in coherence, not NLL
assert_eq!(self.infcx.trait_object_mode(),
relate::TraitObjectMode::NoSquash);
relate::TraitObjectMode::NoSquash
}

fn tag(&self) -> &'static str {
"nll::subtype"
}
Expand Down Expand Up @@ -693,13 +686,6 @@ where
self.infcx.tcx
}

fn trait_object_mode(&self) -> relate::TraitObjectMode {
// squashing should only be done in coherence, not NLL
assert_eq!(self.infcx.trait_object_mode(),
relate::TraitObjectMode::NoSquash);
relate::TraitObjectMode::NoSquash
}

fn tag(&self) -> &'static str {
"nll::generalizer"
}
Expand Down
6 changes: 1 addition & 5 deletions src/librustc/infer/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use traits::Obligation;
use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::fold::TypeFoldable;
use ty::relate::{self, Cause, Relate, RelateResult, TypeRelation};
use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use std::mem;

/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
Expand Down Expand Up @@ -33,10 +33,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
for Sub<'combine, 'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Sub" }
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}

fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
fn a_is_expected(&self) -> bool { self.a_is_expected }

Expand Down
20 changes: 11 additions & 9 deletions src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause};
use traits::IntercrateMode;
use traits::select::IntercrateAmbiguityCause;
use ty::{self, Ty, TyCtxt};
use ty::relate::TraitObjectMode;
use ty::fold::TypeFoldable;
use ty::subst::Subst;

Expand Down Expand Up @@ -55,7 +54,6 @@ pub fn overlapping_impls<'gcx, F1, F2, R>(
impl1_def_id: DefId,
impl2_def_id: DefId,
intercrate_mode: IntercrateMode,
trait_object_mode: TraitObjectMode,
on_overlap: F1,
no_overlap: F2,
) -> R
Expand All @@ -66,14 +64,12 @@ where
debug!("overlapping_impls(\
impl1_def_id={:?}, \
impl2_def_id={:?},
intercrate_mode={:?},
trait_object_mode={:?})",
intercrate_mode={:?})",
impl1_def_id,
impl2_def_id,
intercrate_mode,
trait_object_mode);
intercrate_mode);

let overlaps = tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
let overlaps = tcx.infer_ctxt().enter(|infcx| {
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
overlap(selcx, impl1_def_id, impl2_def_id).is_some()
});
Expand All @@ -85,7 +81,7 @@ where
// In the case where we detect an error, run the check again, but
// this time tracking intercrate ambuiguity causes for better
// diagnostics. (These take time and can lead to false errors.)
tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
tcx.infer_ctxt().enter(|infcx| {
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
selcx.enable_tracking_intercrate_ambiguity_causes();
on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap())
Expand Down Expand Up @@ -485,7 +481,13 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
ty::Foreign(did) => def_id_is_local(did, in_crate),

ty::Dynamic(ref tt, ..) => def_id_is_local(tt.principal().def_id(), in_crate),
ty::Dynamic(ref tt, ..) => {
if let Some(principal) = tt.principal() {
def_id_is_local(principal.def_id(), in_crate)
} else {
false
}
}

ty::Error => true,

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
{
let simp = fast_reject::simplify_type(self.tcx,
trait_ref.skip_binder().self_ty(),
true,);
true);
let all_impls = self.tcx.all_impls(trait_ref.def_id());

match simp {
Expand Down
36 changes: 19 additions & 17 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use infer::{InferCtxt, InferOk, TypeFreshener};
use middle::lang_items;
use mir::interpret::GlobalId;
use ty::fast_reject;
use ty::relate::{TypeRelation, TraitObjectMode};
use ty::relate::TypeRelation;
use ty::subst::{Subst, Substs};
use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};

Expand Down Expand Up @@ -1416,13 +1416,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
return false;
}

// Same idea as the above, but for alt trait object modes. These
// should only be used in intercrate mode - better safe than sorry.
if self.infcx.trait_object_mode() != TraitObjectMode::NoSquash {
bug!("using squashing TraitObjectMode outside of intercrate mode? param_env={:?}",
param_env);
}

// Otherwise, we can use the global cache.
true
}
Expand Down Expand Up @@ -2016,7 +2009,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
return;
}

data.principal().with_self_ty(self.tcx(), self_ty)
if let Some(principal) = data.principal() {
principal.with_self_ty(self.tcx(), self_ty)
} else {
// Only auto-trait bounds exist.
return;
}
}
ty::Infer(ty::TyVar(_)) => {
debug!("assemble_candidates_from_object_ty: ambiguous");
Expand Down Expand Up @@ -2108,7 +2106,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
//
// We always upcast when we can because of reason
// #2 (region bounds).
data_a.principal().def_id() == data_b.principal().def_id()
data_a.principal_def_id() == data_b.principal_def_id()
&& data_b.auto_traits()
// All of a's auto traits need to be in b's auto traits.
.all(|b| data_a.auto_traits().any(|a| a == b))
Expand Down Expand Up @@ -2262,7 +2260,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ImplCandidate(victim_def) => {
let tcx = self.tcx().global_tcx();
return tcx.specializes((other_def, victim_def))
|| tcx.impls_are_allowed_to_overlap(other_def, victim_def);
|| tcx.impls_are_allowed_to_overlap(
other_def, victim_def).is_some();
}
ParamCandidate(ref cand) => {
// Prefer the impl to a global where clause candidate.
Expand Down Expand Up @@ -2919,7 +2918,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let self_ty = self.infcx
.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty {
ty::Dynamic(ref data, ..) => data.principal().with_self_ty(self.tcx(), self_ty),
ty::Dynamic(ref data, ..) =>
data.principal().unwrap_or_else(|| {
span_bug!(obligation.cause.span, "object candidate with no principal")
}).with_self_ty(self.tcx(), self_ty),
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
};

Expand Down Expand Up @@ -3222,8 +3224,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
// See assemble_candidates_for_unsizing for more info.
let existential_predicates = data_a.map_bound(|data_a| {
let iter = iter::once(ty::ExistentialPredicate::Trait(data_a.principal()))
.chain(
let iter =
data_a.principal().map(|x| ty::ExistentialPredicate::Trait(x))
.into_iter().chain(
data_a
.projection_bounds()
.map(|x| ty::ExistentialPredicate::Projection(x)),
Expand Down Expand Up @@ -3260,7 +3263,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// T -> Trait.
(_, &ty::Dynamic(ref data, r)) => {
let mut object_dids = data.auto_traits()
.chain(iter::once(data.principal().def_id()));
.chain(data.principal_def_id());
if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
return Err(TraitNotObjectSafe(did));
}
Expand Down Expand Up @@ -3571,8 +3574,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
previous: &ty::PolyTraitRef<'tcx>,
current: &ty::PolyTraitRef<'tcx>,
) -> bool {
let mut matcher = ty::_match::Match::new(
self.tcx(), self.infcx.trait_object_mode());
let mut matcher = ty::_match::Match::new(self.tcx());
matcher.relate(previous, current).is_ok()
}

Expand Down
3 changes: 1 addition & 2 deletions src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ pub mod specialization_graph;
use hir::def_id::DefId;
use infer::{InferCtxt, InferOk};
use lint;
use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
use traits::coherence;
use traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use syntax_pos::DUMMY_SP;
Expand Down
Loading