Rollup merge of #68140 - ecstatic-morse:const-trait-bound-opt-out, r=oli-obk

Implement `?const` opt-out for trait bounds

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

Prior to this PR, the constness of a trait bound/impl was stored in `TraitRef`. Now, the constness of an `impl` is stored in `ast::ItemKind::Impl` and the constness of a bound in `ast::TraitBoundModifer`. Additionally, constness of trait bounds is now stored in an additional field of `ty::Predicate::Trait`, and the combination of the constness of the item along with any `TraitBoundModifier` determines the constness of the bound in accordance with the RFC. Encoding the constness of impls at the `ty` level is left for a later PR.

After a discussion in \#wg-grammar on Discord, it was decided that the grammar should not encode the mutual exclusivity of trait bound modifiers. The grammar for trait bound modifiers remains `[?const] [?]`. To encode this, I add a dummy variant to `ast::TraitBoundModifier` that is used when the syntax `?const ?` appears. This variant causes an error in AST validation and disappears during HIR lowering.

cc #67794

r? @oli-obk
This commit is contained in:
Mazdak Farrokhzad 2020-01-21 19:42:20 +01:00 committed by GitHub
commit 3484e2fab4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
71 changed files with 495 additions and 311 deletions

View file

@ -462,7 +462,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
.filter(|p| {
!orig_bounds.contains(p)
|| match p {
&&ty::Predicate::Trait(pred) => pred.def_id() == sized_trait,
ty::Predicate::Trait(pred, _) => pred.def_id() == sized_trait,
_ => false,
}
})

View file

@ -1,7 +1,7 @@
use rustc::infer::InferOk;
use rustc::traits;
use rustc::ty::subst::Subst;
use rustc::ty::ToPredicate;
use rustc::ty::{ToPredicate, WithConstness};
use rustc_hir as hir;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_span::DUMMY_SP;
@ -64,7 +64,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
match infcx.evaluate_obligation(&traits::Obligation::new(
cause,
param_env,
trait_ref.to_predicate(),
trait_ref.without_const().to_predicate(),
)) {
Ok(eval_result) => eval_result.may_apply(),
Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no

View file

@ -482,7 +482,7 @@ impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
use rustc::ty::Predicate;
match *self {
Predicate::Trait(ref pred) => Some(pred.clean(cx)),
Predicate::Trait(ref pred, _) => Some(pred.clean(cx)),
Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
Predicate::RegionOutlives(ref pred) => pred.clean(cx),
Predicate::TypeOutlives(ref pred) => pred.clean(cx),

View file

@ -141,7 +141,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId)
.predicates
.iter()
.filter_map(|(pred, _)| {
if let ty::Predicate::Trait(ref pred) = *pred {
if let ty::Predicate::Trait(ref pred, _) = *pred {
if pred.skip_binder().trait_ref.self_ty() == self_ty {
Some(pred.def_id())
} else {

View file

@ -203,6 +203,7 @@ pub struct Impl<'hir> {
pub unsafety: hir::Unsafety,
pub polarity: hir::ImplPolarity,
pub defaultness: hir::Defaultness,
pub constness: ast::Constness,
pub generics: &'hir hir::Generics<'hir>,
pub trait_: &'hir Option<hir::TraitRef<'hir>>,
pub for_: &'hir hir::Ty<'hir>,

View file

@ -361,6 +361,7 @@ impl clean::GenericBound {
let modifier_str = match modifier {
hir::TraitBoundModifier::None => "",
hir::TraitBoundModifier::Maybe => "?",
hir::TraitBoundModifier::MaybeConst => "?const",
};
if f.alternate() {
write!(f, "{}{:#}", modifier_str, ty.print())

View file

@ -562,6 +562,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
unsafety,
polarity,
defaultness,
constness,
ref generics,
ref of_trait,
self_ty,
@ -576,6 +577,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
unsafety,
polarity,
defaultness,
constness,
generics,
trait_: of_trait,
for_: self_ty,