Skip to content

Commit

Permalink
Auto merge of #68140 - ecstatic-morse:const-trait-bound-opt-out, r=<try>
Browse files Browse the repository at this point in the history
Support `?const` opt-out for trait bounds

For now, such bounds are treated exactly the same as unprefixed ones in all contexts. [RFC 2632](rust-lang/rfcs#2632) does not specify whether such bounds are forbidden outside of `const` contexts, so they are allowed at the moment.

cc #67794

r? @oli-obk
  • Loading branch information
bors committed Jan 12, 2020
2 parents f363745 + c37571d commit 4c4563c
Show file tree
Hide file tree
Showing 38 changed files with 155 additions and 202 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,10 @@ impl NiceRegionError<'me, 'tcx> {
false
};

let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
def_id: trait_def_id,
substs: expected_substs,
});
let actual_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
def_id: trait_def_id,
substs: actual_substs,
});
let expected_trait_ref =
self.infcx.resolve_vars_if_possible(&ty::TraitRef::new(trait_def_id, expected_substs));
let actual_trait_ref =
self.infcx.resolve_vars_if_possible(&ty::TraitRef::new(trait_def_id, actual_substs));

// Search the expected and actual trait references to see (a)
// whether the sub/sup placeholders appear in them (sometimes
Expand Down
7 changes: 2 additions & 5 deletions src/librustc/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
) -> AutoTraitResult<A> {
let tcx = self.tcx;

let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
let trait_ref = ty::TraitRef::new(trait_did, tcx.mk_substs_trait(ty, &[]));

let trait_pred = ty::Binder::bind(trait_ref);

Expand Down Expand Up @@ -271,10 +271,7 @@ impl AutoTraitFinder<'tcx> {
let mut already_visited = FxHashSet::default();
let mut predicates = VecDeque::new();
predicates.push_back(ty::Binder::bind(ty::TraitPredicate {
trait_ref: ty::TraitRef {
def_id: trait_did,
substs: infcx.tcx.mk_substs_trait(ty, &[]),
},
trait_ref: ty::TraitRef::new(trait_did, infcx.tcx.mk_substs_trait(ty, &[])),
}));

let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
def_id: DefId,
cause: ObligationCause<'tcx>,
) {
let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
let trait_ref = ty::TraitRef::new(def_id, infcx.tcx.mk_substs_trait(ty, &[]));
self.register_predicate_obligation(
infcx,
Obligation {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1340,8 +1340,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> PredicateObligation<'tcx> {
let new_trait_ref =
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
let new_trait_ref = ty::TraitRef::new(def_id, self.tcx.mk_substs_trait(output_ty, &[]));
Obligation::new(cause, param_env, new_trait_ref.to_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 @@ -72,7 +72,7 @@ pub struct PendingPredicateObligation<'tcx> {

// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(PendingPredicateObligation<'_>, 136);
static_assert_size!(PendingPredicateObligation<'_>, 144);

impl<'a, 'tcx> FulfillmentContext<'tcx> {
/// Creates a new fulfillment context.
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;

// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(PredicateObligation<'_>, 112);
static_assert_size!(PredicateObligation<'_>, 120);

/// The reason why we incurred this obligation; used for error reporting.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -320,7 +320,7 @@ pub struct AssocTypeBoundData {

// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(ObligationCauseCode<'_>, 32);
static_assert_size!(ObligationCauseCode<'_>, 40);

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct MatchExpressionArmCause<'tcx> {
Expand Down Expand Up @@ -727,7 +727,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
infcx.tcx.def_path_str(def_id)
);

let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
let trait_ref = ty::TraitRef::new(def_id, infcx.tcx.mk_substs_trait(ty, &[]));
let obligation = Obligation {
param_env,
cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
Expand Down
18 changes: 9 additions & 9 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,10 +579,10 @@ fn receiver_is_dispatchable<'tcx>(
let mut param_env = tcx.param_env(method.def_id);

// Self: Unsize<U>
let unsize_predicate = ty::TraitRef {
def_id: unsize_did,
substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
}
let unsize_predicate = ty::TraitRef::new(
unsize_did,
tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
)
.to_predicate();

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

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

let caller_bounds: Vec<Predicate<'tcx>> = param_env
Expand All @@ -614,10 +614,10 @@ fn receiver_is_dispatchable<'tcx>(

// Receiver: DispatchFromDyn<Receiver[Self => U]>
let obligation = {
let predicate = ty::TraitRef {
def_id: dispatch_from_dyn_did,
substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
}
let predicate = ty::TraitRef::new(
dispatch_from_dyn_did,
tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
)
.to_predicate();

Obligation::new(ObligationCause::dummy(), param_env, predicate)
Expand Down
12 changes: 4 additions & 8 deletions src/librustc/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,7 @@ pub fn predicate_for_trait_def(
self_ty: Ty<'tcx>,
params: &[GenericArg<'tcx>],
) -> PredicateObligation<'tcx> {
let trait_ref =
ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
let trait_ref = ty::TraitRef::new(trait_def_id, tcx.mk_substs_trait(self_ty, params));
predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
}

Expand Down Expand Up @@ -629,10 +628,8 @@ pub fn closure_trait_ref_and_return_type(
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
};
let trait_ref = ty::TraitRef {
def_id: fn_trait_def_id,
substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
};
let trait_ref =
ty::TraitRef::new(fn_trait_def_id, tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]));
ty::Binder::bind((trait_ref, sig.skip_binder().output()))
}

Expand All @@ -642,8 +639,7 @@ pub fn generator_trait_ref_and_outputs(
self_ty: Ty<'tcx>,
sig: ty::PolyGenSig<'tcx>,
) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
let trait_ref =
ty::TraitRef { def_id: fn_trait_def_id, substs: tcx.mk_substs_trait(self_ty, &[]) };
let trait_ref = ty::TraitRef::new(fn_trait_def_id, tcx.mk_substs_trait(self_ty, &[]));
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
}

Expand Down
8 changes: 4 additions & 4 deletions src/librustc/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
if !subty.has_escaping_bound_vars() {
let cause = self.cause(cause);
let trait_ref = ty::TraitRef {
def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
};
let trait_ref = ty::TraitRef::new(
self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
self.infcx.tcx.mk_substs_trait(subty, &[]),
);
self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate()));
}
}
Expand Down
8 changes: 3 additions & 5 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2467,11 +2467,9 @@ impl<'tcx> AdtDef {
Some(x) => x,
_ => return vec![ty],
};
let sized_predicate = Binder::dummy(TraitRef {
def_id: sized_trait,
substs: tcx.mk_substs_trait(ty, &[]),
})
.to_predicate();
let sized_predicate =
Binder::dummy(TraitRef::new(sized_trait, tcx.mk_substs_trait(ty, &[])))
.to_predicate();
let predicates = tcx.predicates_of(self.did).predicates;
if predicates.iter().any(|(p, _)| *p == sized_predicate) {
vec![]
Expand Down
8 changes: 7 additions & 1 deletion src/librustc/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1749,7 +1749,13 @@ define_print_and_forward_display! {
}

ty::TraitRef<'tcx> {
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
p!(
write("<{} as {}{}>",
self.self_ty(),
if self.maybe_const { "?const " } else { "" },
self.print_only_trait_path()
)
)
}

TraitRefPrintOnlyTraitPath<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
} else {
let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
Ok(ty::TraitRef::new(a.def_id, substs))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec<I, T> {
impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
type Lifted = ty::TraitRef<'tcx>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(&self.substs).map(|substs| ty::TraitRef { def_id: self.def_id, substs })
tcx.lift(&self.substs).map(|substs| ty::TraitRef::new(self.def_id, substs))
}
}

Expand Down
28 changes: 21 additions & 7 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,8 +670,7 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty)))
}
ExistentialPredicate::AutoTrait(did) => {
let trait_ref =
Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
let trait_ref = Binder(ty::TraitRef::new(did, tcx.mk_substs_trait(self_ty, &[])));
trait_ref.to_predicate()
}
}
Expand Down Expand Up @@ -784,17 +783,32 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
pub struct TraitRef<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,

/// Whether the reference to the trait is prefixed by `?const`.
//
// FIXME(ecstaticmorse): This field causes `TraitRef` to increase in size by an entire machine
// word, despite it never being used during trait solving. Try implementing the checks in
// `qualify_min_const_fn` using `hir::TraitRef` instead.
pub maybe_const: bool,
}

impl<'tcx> TraitRef<'tcx> {
pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
TraitRef { def_id, substs }
TraitRef::new_maybe_const(def_id, substs, false)
}

pub fn new_maybe_const(
def_id: DefId,
substs: SubstsRef<'tcx>,
maybe_const: bool,
) -> TraitRef<'tcx> {
TraitRef { def_id, substs, maybe_const }
}

/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
/// are the parameters defined on trait.
pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> {
TraitRef { def_id, substs: InternalSubsts::identity_for_item(tcx, def_id) }
TraitRef::new(def_id, InternalSubsts::identity_for_item(tcx, def_id))
}

#[inline]
Expand All @@ -817,7 +831,7 @@ impl<'tcx> TraitRef<'tcx> {
) -> ty::TraitRef<'tcx> {
let defs = tcx.generics_of(trait_id);

ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
ty::TraitRef::new(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
}
}

Expand Down Expand Up @@ -882,7 +896,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
// otherwise the escaping vars would be captured by the binder
// debug_assert!(!self_ty.has_escaping_bound_vars());

ty::TraitRef { def_id: self.def_id, substs: tcx.mk_substs_trait(self_ty, self.substs) }
ty::TraitRef::new(self.def_id, tcx.mk_substs_trait(self_ty, self.substs))
}
}

Expand Down Expand Up @@ -1058,7 +1072,7 @@ impl<'tcx> ProjectionTy<'tcx> {
/// then this function would return a `T: Iterator` trait reference.
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
let def_id = tcx.associated_item(self.item_def_id).container.id();
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
ty::TraitRef::new(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
}

pub fn self_ty(&self) -> Ty<'tcx> {
Expand Down
15 changes: 7 additions & 8 deletions src/librustc_ast_lowering/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1977,13 +1977,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// ::std::future::Future<future_params>
let future_path =
self.std_path(span, &[sym::future, sym::Future], Some(future_params), false);
let future_trait_ref =
hir::TraitRef { path: future_path, hir_ref_id: self.next_id(), constness: None };

hir::GenericBound::Trait(
hir::PolyTraitRef {
trait_ref: hir::TraitRef { path: future_path, hir_ref_id: self.next_id() },
bound_generic_params: &[],
span,
},
hir::PolyTraitRef { trait_ref: future_trait_ref, bound_generic_params: &[], span },
hir::TraitBoundModifier::None,
)
}
Expand Down Expand Up @@ -2149,7 +2147,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::QPath::Resolved(None, path) => path,
qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
};
hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }

hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id), constness: p.constness }
}

fn lower_poly_trait_ref(
Expand All @@ -2158,7 +2157,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::PolyTraitRef<'hir> {
if p.trait_ref.constness.is_some() {
self.diagnostic().span_err(p.span, "`?const` on trait bounds is not yet implemented");
// self.diagnostic().span_err(p.span, "`?const` on trait bounds is not yet implemented");
}

let bound_generic_params = self.lower_generic_params(
Expand Down Expand Up @@ -2463,8 +2462,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Res::Def(DefKind::Trait, _) | Res::Def(DefKind::TraitAlias, _) => {
let principal = hir::PolyTraitRef {
bound_generic_params: &[],
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
span,
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id, constness: None },
};

// The original ID is taken by the `PolyTraitRef`,
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_hir/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2233,6 +2233,8 @@ pub struct TraitRef<'hir> {
// Don't hash the `ref_id`. It is tracked via the thing it is used to access.
#[stable_hasher(ignore)]
pub hir_ref_id: HirId,

pub constness: Option<Constness>,
}

impl TraitRef<'_> {
Expand All @@ -2247,6 +2249,10 @@ impl TraitRef<'_> {
_ => unreachable!(),
}
}

pub fn is_maybe_const(&self) -> bool {
self.constness == Some(Constness::NotConst)
}
}

#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
Expand Down
Loading

0 comments on commit 4c4563c

Please sign in to comment.