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 coherence future-compat warnings for marker-only trait objects #56481

Merged
merged 5 commits into from
Dec 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
7 changes: 7 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ declare_lint! {
"potentially-conflicting impls were erroneously allowed"
}

declare_lint! {
pub ORDER_DEPENDENT_TRAIT_OBJECTS,
Deny,
"trait-object types were treated as different depending on marker-trait order"
}

declare_lint! {
pub BAD_REPR,
Warn,
Expand Down Expand Up @@ -405,6 +411,7 @@ impl LintPass for HardwiredLints {
PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
LATE_BOUND_LIFETIME_ARGUMENTS,
INCOHERENT_FUNDAMENTAL_IMPLS,
ORDER_DEPENDENT_TRAIT_OBJECTS,
DEPRECATED,
UNUSED_UNSAFE,
UNUSED_MUT,
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