Skip to content

Commit

Permalink
add coherence future-compat warnings for marker-only trait objects
Browse files Browse the repository at this point in the history
The future-compat warnings break code that assumes that `dyn Send + Sync !=
dyn Sync + Send`, and are the first step in making them equal. cc rust-lang#33140.

It should be possible to revert this commit when we're done with the
warnings.
  • Loading branch information
arielb1 committed Dec 14, 2018
1 parent 3882567 commit 7606396
Show file tree
Hide file tree
Showing 21 changed files with 433 additions and 56 deletions.
4 changes: 4 additions & 0 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,10 @@ 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: 4 additions & 0 deletions src/librustc/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ 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: 5 additions & 1 deletion src/librustc/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use super::Subtype;

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

/// "Greatest lower bound" (common subtype)
pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
Expand All @@ -36,6 +36,10 @@ 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: 5 additions & 1 deletion src/librustc/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use super::Subtype;

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

/// "Least upper bound" (common supertype)
pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
Expand All @@ -36,6 +36,10 @@ 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: 18 additions & 1 deletion src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,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;
use ty::relate::{RelateResult, TraitObjectMode};
use ty::subst::{Kind, Substs};
use ty::{self, GenericParamDefKind, Ty, TyCtxt};
use ty::{FloatVid, IntVid, TyVid};
Expand Down Expand Up @@ -182,6 +182,9 @@ 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 @@ -472,6 +475,7 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
arena: SyncDroplessArena,
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
trait_object_mode: TraitObjectMode,
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
Expand All @@ -480,6 +484,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
global_tcx: self,
arena: SyncDroplessArena::default(),
fresh_tables: None,
trait_object_mode: TraitObjectMode::NoSquash,
}
}
}
Expand All @@ -492,6 +497,12 @@ 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 @@ -518,6 +529,7 @@ 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 fresh_tables,
} = *self;
Expand All @@ -526,6 +538,7 @@ 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 @@ -607,6 +620,10 @@ 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: 14 additions & 0 deletions src/librustc/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,13 @@ 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 @@ -696,6 +703,13 @@ 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: 5 additions & 1 deletion src/librustc/infer/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use traits::Obligation;
use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::fold::TypeFoldable;
use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use ty::relate::{self, Cause, Relate, RelateResult, TypeRelation};
use std::mem;

/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
Expand Down Expand Up @@ -43,6 +43,10 @@ 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
12 changes: 8 additions & 4 deletions src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ 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 @@ -52,6 +53,7 @@ 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 @@ -62,12 +64,14 @@ where
debug!("overlapping_impls(\
impl1_def_id={:?}, \
impl2_def_id={:?},
intercrate_mode={:?})",
intercrate_mode={:?},
trait_object_mode={:?})",
impl1_def_id,
impl2_def_id,
intercrate_mode);
intercrate_mode,
trait_object_mode);

let overlaps = tcx.infer_ctxt().enter(|infcx| {
let overlaps = tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
overlap(selcx, impl1_def_id, impl2_def_id).is_some()
});
Expand All @@ -79,7 +83,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().enter(|infcx| {
tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).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
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,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
2 changes: 2 additions & 0 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
pub use self::specialize::find_associated_item;
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
pub use self::engine::{TraitEngine, TraitEngineExt};
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds,
Expand Down
12 changes: 10 additions & 2 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use infer::{InferCtxt, InferOk, TypeFreshener};
use middle::lang_items;
use mir::interpret::GlobalId;
use ty::fast_reject;
use ty::relate::TypeRelation;
use ty::relate::{TypeRelation, TraitObjectMode};
use ty::subst::{Subst, Substs};
use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};

Expand Down Expand Up @@ -1501,6 +1501,13 @@ 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 @@ -3699,7 +3706,8 @@ 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());
let mut matcher = ty::_match::Match::new(
self.tcx(), self.infcx.trait_object_mode());
matcher.relate(previous, current).is_ok()
}

Expand Down
20 changes: 14 additions & 6 deletions src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ pub mod specialization_graph;
use hir::def_id::DefId;
use infer::{InferCtxt, InferOk};
use lint;
use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use syntax_pos::DUMMY_SP;
use traits::{self, ObligationCause, TraitEngine};
use traits::select::IntercrateAmbiguityCause;
use ty::{self, TyCtxt, TypeFoldable};
use ty::subst::{Subst, Substs};
Expand All @@ -36,6 +36,7 @@ use super::{SelectionContext, FulfillmentContext};
use super::util::impl_trait_ref_and_oblig;

/// Information pertinent to an overlapping impl error.
#[derive(Debug)]
pub struct OverlapError {
pub with_impl: DefId,
pub trait_desc: String,
Expand Down Expand Up @@ -318,8 +319,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
let insert_result = sg.insert(tcx, impl_def_id);
// Report error if there was one.
let (overlap, used_to_be_allowed) = match insert_result {
Err(overlap) => (Some(overlap), false),
Ok(opt_overlap) => (opt_overlap, true)
Err(overlap) => (Some(overlap), None),
Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)),
Ok(None) => (None, None)
};

if let Some(overlap) = overlap {
Expand All @@ -329,14 +331,20 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
String::new(), |ty| {
format!(" for type `{}`", ty)
}),
if used_to_be_allowed { " (E0119)" } else { "" }
if used_to_be_allowed.is_some() { " (E0119)" } else { "" }
);
let impl_span = tcx.sess.source_map().def_span(
tcx.span_of_impl(impl_def_id).unwrap()
);
let mut err = if used_to_be_allowed {
let mut err = if let Some(kind) = used_to_be_allowed {
let lint = match kind {
FutureCompatOverlapErrorKind::Issue43355 =>
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
FutureCompatOverlapErrorKind::Issue33140 =>
lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
};
tcx.struct_span_lint_node(
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
lint,
tcx.hir().as_local_node_id(impl_def_id).unwrap(),
impl_span,
&msg)
Expand Down
Loading

0 comments on commit 7606396

Please sign in to comment.