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

Implement ?const opt-out for trait bounds #68140

Merged
merged 12 commits into from
Jan 21, 2020
9 changes: 6 additions & 3 deletions src/librustc/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,10 @@ impl AutoTraitFinder<'tcx> {
&Err(SelectionError::Unimplemented) => {
if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
already_visited.remove(&pred);
self.add_user_pred(&mut user_computed_preds, ty::Predicate::Trait(pred));
self.add_user_pred(
&mut user_computed_preds,
ty::Predicate::Trait(pred, ast::Constness::NotConst),
);
predicates.push_back(pred);
} else {
debug!(
Expand Down Expand Up @@ -405,7 +408,7 @@ impl AutoTraitFinder<'tcx> {
let mut should_add_new = true;
user_computed_preds.retain(|&old_pred| {
match (&new_pred, old_pred) {
(&ty::Predicate::Trait(new_trait), ty::Predicate::Trait(old_trait)) => {
(&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
if new_trait.def_id() == old_trait.def_id() {
let new_substs = new_trait.skip_binder().trait_ref.substs;
let old_substs = old_trait.skip_binder().trait_ref.substs;
Expand Down Expand Up @@ -627,7 +630,7 @@ impl AutoTraitFinder<'tcx> {
// We check this by calling is_of_param on the relevant types
// from the various possible predicates
match &predicate {
&ty::Predicate::Trait(p) => {
&ty::Predicate::Trait(p, _) => {
if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
&& !only_projections
&& is_new_pred
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/engine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::infer::InferCtxt;
use crate::traits::Obligation;
use crate::ty::{self, ToPredicate, Ty, TyCtxt};
use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_hir::def_id::DefId;

use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
Expand Down Expand Up @@ -33,7 +33,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
cause,
recursion_depth: 0,
param_env,
predicate: trait_ref.to_predicate(),
predicate: trait_ref.without_const().to_predicate(),
},
);
}
Expand Down
28 changes: 18 additions & 10 deletions src/librustc/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ use crate::ty::error::ExpectedFound;
use crate::ty::fast_reject;
use crate::ty::fold::TypeFolder;
use crate::ty::SubtypePredicate;
use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::ty::{
self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
};

use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
Expand Down Expand Up @@ -130,15 +132,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

let (cond, error) = match (cond, error) {
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
_ => {
// FIXME: make this work in other cases too.
return false;
}
};

for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
if let ty::Predicate::Trait(implication) = implication {
if let ty::Predicate::Trait(implication, _) = implication {
let error = error.to_poly_trait_ref();
let implication = implication.to_poly_trait_ref();
// FIXME: I'm just not taking associated types at all here.
Expand Down Expand Up @@ -530,7 +532,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return;
}
match obligation.predicate {
ty::Predicate::Trait(ref trait_predicate) => {
ty::Predicate::Trait(ref trait_predicate, _) => {
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);

if self.tcx.sess.has_errors() && trait_predicate.references_error() {
Expand Down Expand Up @@ -583,7 +585,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"{}",
message.unwrap_or_else(|| format!(
"the trait bound `{}` is not satisfied{}",
trait_ref.to_predicate(),
trait_ref.without_const().to_predicate(),
post_message,
))
);
Expand Down Expand Up @@ -695,7 +697,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
trait_pred
});
let unit_obligation = Obligation {
predicate: ty::Predicate::Trait(predicate),
predicate: ty::Predicate::Trait(
predicate,
ast::Constness::NotConst,
),
..obligation.clone()
};
if self.predicate_may_hold(&unit_obligation) {
Expand Down Expand Up @@ -988,7 +993,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) -> PredicateObligation<'tcx> {
let new_trait_ref =
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
Obligation::new(cause, param_env, new_trait_ref.to_predicate())
Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
}
}

Expand Down Expand Up @@ -1076,7 +1081,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

let mut err = match predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
let trait_ref = data.to_poly_trait_ref();
let self_ty = trait_ref.self_ty();
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
Expand Down Expand Up @@ -1269,8 +1274,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
)
.value;

let obligation =
Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
let obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
cleaned_pred.without_const().to_predicate(),
);

self.predicate_may_hold(&obligation)
})
Expand Down
17 changes: 10 additions & 7 deletions src/librustc/traits/error_reporting/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{
use crate::infer::InferCtxt;
use crate::traits::object_safety::object_safety_violations;
use crate::ty::TypeckTables;
use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};

use rustc_errors::{
error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
Expand Down Expand Up @@ -50,7 +50,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} else {
" where"
},
trait_ref.to_predicate(),
trait_ref.without_const().to_predicate(),
),
Applicability::MachineApplicable,
);
Expand Down Expand Up @@ -340,8 +340,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
let new_obligation =
Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
let new_obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
new_trait_ref.without_const().to_predicate(),
);
if self.predicate_must_hold_modulo_regions(&new_obligation) {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
// We have a very specific type of error, where just borrowing this argument
Expand Down Expand Up @@ -1122,7 +1125,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// the type. The last generator has information about where the bound was introduced. At
// least one generator should be present for this diagnostic to be modified.
let (mut trait_ref, mut target_ty) = match obligation.predicate {
ty::Predicate::Trait(p) => {
ty::Predicate::Trait(p, _) => {
(Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
}
_ => (None, None),
Expand Down Expand Up @@ -1545,7 +1548,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.note(&format!("required because it appears within the type `{}`", ty));
obligated_types.push(ty);

let parent_predicate = parent_trait_ref.to_predicate();
let parent_predicate = parent_trait_ref.without_const().to_predicate();
if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
self.note_obligation_cause_code(
err,
Expand All @@ -1562,7 +1565,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
parent_trait_ref.print_only_trait_path(),
parent_trait_ref.skip_binder().self_ty()
));
let parent_predicate = parent_trait_ref.to_predicate();
let parent_predicate = parent_trait_ref.without_const().to_predicate();
self.note_obligation_cause_code(
err,
&parent_predicate,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
}

match obligation.predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
let trait_obligation = obligation.with(data.clone());

if data.is_global() {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::mir::interpret::ErrorHandled;
use crate::ty::error::{ExpectedFound, TypeError};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt};
use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt, WithConstness};
use crate::util::common::ErrorReported;
use chalk_engine;
use rustc_hir as hir;
Expand Down Expand Up @@ -732,7 +732,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
param_env,
cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
recursion_depth: 0,
predicate: trait_ref.to_predicate(),
predicate: trait_ref.without_const().to_predicate(),
};

let result = infcx.predicate_must_hold_modulo_regions(&obligation);
Expand Down
10 changes: 6 additions & 4 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::elaborate_predicates;

use crate::traits::{self, Obligation, ObligationCause};
use crate::ty::subst::{InternalSubsts, Subst};
use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
Expand Down Expand Up @@ -234,7 +234,7 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o
.map(|(predicate, _)| predicate.subst_supertrait(tcx, &trait_ref))
.any(|predicate| {
match predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
// In the case of a trait predicate, we can skip the "self" type.
data.skip_binder().input_types().skip(1).any(has_self_ty)
}
Expand Down Expand Up @@ -285,7 +285,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;
elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
ty::Predicate::Trait(ref trait_pred) => {
ty::Predicate::Trait(ref trait_pred, _) => {
trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
}
ty::Predicate::Projection(..)
Expand Down Expand Up @@ -585,6 +585,7 @@ fn receiver_is_dispatchable<'tcx>(
def_id: unsize_did,
substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
}
.without_const()
.to_predicate();

// U: Trait<Arg1, ..., ArgN>
Expand All @@ -598,7 +599,7 @@ fn receiver_is_dispatchable<'tcx>(
}
});

ty::TraitRef { def_id: unsize_did, substs }.to_predicate()
ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
};

let caller_bounds: Vec<Predicate<'tcx>> = param_env
Expand All @@ -620,6 +621,7 @@ fn receiver_is_dispatchable<'tcx>(
def_id: dispatch_from_dyn_did,
substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
}
.without_const()
.to_predicate();

Obligation::new(ObligationCause::dummy(), param_env, predicate)
Expand Down
11 changes: 8 additions & 3 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use crate::ty::fold::{TypeFoldable, TypeFolder};
use crate::ty::subst::{InternalSubsts, Subst};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
Expand Down Expand Up @@ -738,7 +738,12 @@ fn get_paranoid_cache_value_obligation<'a, 'tcx>(
depth: usize,
) -> PredicateObligation<'tcx> {
let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() }
Obligation {
cause,
recursion_depth: depth,
param_env,
predicate: trait_ref.without_const().to_predicate(),
}
}

/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
Expand Down Expand Up @@ -772,7 +777,7 @@ fn normalize_to_error<'a, 'tcx>(
cause,
recursion_depth: depth,
param_env,
predicate: trait_ref.to_predicate(),
predicate: trait_ref.without_const().to_predicate(),
};
let tcx = selcx.infcx().tcx;
let def_id = projection_ty.item_def_id;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/query/type_op/prove_predicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
// `&T`, accounts for about 60% percentage of the predicates
// we have to prove. No need to canonicalize and all that for
// such cases.
if let Predicate::Trait(trait_ref) = key.value.predicate {
if let Predicate::Trait(trait_ref, _) = key.value.predicate {
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
if trait_ref.def_id() == sized_def_id {
if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
Expand Down
14 changes: 8 additions & 6 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::middle::lang_items;
use crate::ty::fast_reject;
use crate::ty::relate::TypeRelation;
use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_hir::def_id::DefId;

use rustc_data_structures::fx::{FxHashMap, FxHashSet};
Expand All @@ -51,7 +51,7 @@ use std::cmp;
use std::fmt::{self, Display};
use std::iter;
use std::rc::Rc;
use syntax::attr;
use syntax::{ast, attr};

pub struct SelectionContext<'cx, 'tcx> {
infcx: &'cx InferCtxt<'cx, 'tcx>,
Expand Down Expand Up @@ -718,7 +718,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}

match obligation.predicate {
ty::Predicate::Trait(ref t) => {
ty::Predicate::Trait(ref t, _) => {
debug_assert!(!t.has_escaping_bound_vars());
let obligation = obligation.with(t.clone());
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
Expand Down Expand Up @@ -945,7 +945,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// trait refs. This is important because it's only a cycle
// if the regions match exactly.
let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
let cycle = cycle.map(|stack| {
ty::Predicate::Trait(stack.obligation.predicate, ast::Constness::NotConst)
});
if self.coinductive_match(cycle) {
debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
Some(EvaluatedToOk)
Expand Down Expand Up @@ -1060,7 +1062,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
let result = match predicate {
ty::Predicate::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()),
ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
_ => false,
};
debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
Expand Down Expand Up @@ -3366,7 +3368,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
tcx.mk_substs_trait(source, &[]),
);
nested.push(predicate_to_obligation(tr.to_predicate()));
nested.push(predicate_to_obligation(tr.without_const().to_predicate()));

// If the type is `Foo + 'a`, ensure that the type
// being cast to `Foo + 'a` outlives `'a`:
Expand Down
Loading