mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Auto merge of #79345 - jonas-schievink:rollup-1yhhzx9, r=jonas-schievink
Rollup of 10 pull requests Successful merges: - #76829 (stabilize const_int_pow) - #79080 (MIR visitor: Don't treat debuginfo field access as a use of the struct) - #79236 (const_generics: assert resolve hack causes an error) - #79287 (Allow using generic trait methods in `const fn`) - #79324 (Use Option::and_then instead of open-coding it) - #79325 (Reduce boilerplate with the `?` operator) - #79330 (Fix typo in comment) - #79333 (doc typo) - #79337 (Use Option::map instead of open coding it) - #79343 (Add my (`@flip1995)` work mail to the mailmap) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
40624dde6c
1
.mailmap
1
.mailmap
@ -230,6 +230,7 @@ Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com>
|
||||
Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>
|
||||
Philipp Brüschweiler <blei42@gmail.com> <bruphili@student.ethz.ch>
|
||||
Philipp Krones <hello@philkrones.com> flip1995 <hello@philkrones.com>
|
||||
Philipp Krones <hello@philkrones.com> <philipp.krones@embecosm.com>
|
||||
Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de>
|
||||
Przemysław Wesołek <jest@go.art.pl> Przemek Wesołek <jest@go.art.pl>
|
||||
Rafael Ávila de Espíndola <respindola@mozilla.com> Rafael Avila de Espindola <espindola@dream.(none)>
|
||||
|
@ -649,17 +649,13 @@ pub mod shell {
|
||||
impl<'a> Iterator for Substitutions<'a> {
|
||||
type Item = Substitution<'a>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match parse_next_substitution(self.s) {
|
||||
Some((mut sub, tail)) => {
|
||||
self.s = tail;
|
||||
if let Some(InnerSpan { start, end }) = sub.position() {
|
||||
sub.set_position(start + self.pos, end + self.pos);
|
||||
self.pos += end;
|
||||
}
|
||||
Some(sub)
|
||||
}
|
||||
None => None,
|
||||
let (mut sub, tail) = parse_next_substitution(self.s)?;
|
||||
self.s = tail;
|
||||
if let Some(InnerSpan { start, end }) = sub.position() {
|
||||
sub.set_position(start + self.pos, end + self.pos);
|
||||
self.pos += end;
|
||||
}
|
||||
Some(sub)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
|
@ -1152,10 +1152,7 @@ impl<'ll> MemberDescription<'ll> {
|
||||
self.size.bits(),
|
||||
self.align.bits() as u32,
|
||||
self.offset.bits(),
|
||||
match self.discriminant {
|
||||
None => None,
|
||||
Some(value) => Some(cx.const_u64(value)),
|
||||
},
|
||||
self.discriminant.map(|v| cx.const_u64(v)),
|
||||
self.flags,
|
||||
self.type_metadata,
|
||||
)
|
||||
|
@ -37,12 +37,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
||||
/// `funclet_bb` member if it is not `None`.
|
||||
fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
&self,
|
||||
fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
|
||||
fx: &'b FunctionCx<'a, 'tcx, Bx>,
|
||||
) -> Option<&'b Bx::Funclet> {
|
||||
match self.funclet_bb {
|
||||
Some(funcl) => fx.funclets[funcl].as_ref(),
|
||||
None => None,
|
||||
}
|
||||
self.funclet_bb.and_then(|funcl| fx.funclets[funcl].as_ref())
|
||||
}
|
||||
|
||||
fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
|
||||
|
@ -309,7 +309,7 @@ impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToT
|
||||
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
|
||||
while let Some(obligation) = self.base_iterator.next() {
|
||||
if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() {
|
||||
return Some(data);
|
||||
return Some(data.value);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -1017,11 +1017,14 @@ macro_rules! visit_place_fns {
|
||||
let mut context = context;
|
||||
|
||||
if !place.projection.is_empty() {
|
||||
context = if context.is_mutating_use() {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||
} else {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
};
|
||||
if context.is_use() {
|
||||
// ^ Only change the context if it is a real use, not a "use" in debuginfo.
|
||||
context = if context.is_mutating_use() {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||
} else {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
self.visit_local(&place.local, context, location);
|
||||
|
@ -16,6 +16,7 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::Constness;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use smallvec::SmallVec;
|
||||
@ -457,7 +458,7 @@ pub enum ImplSource<'tcx, N> {
|
||||
/// for some type parameter. The `Vec<N>` represents the
|
||||
/// obligations incurred from normalizing the where-clause (if
|
||||
/// any).
|
||||
Param(Vec<N>),
|
||||
Param(Vec<N>, Constness),
|
||||
|
||||
/// Virtual calls through an object.
|
||||
Object(ImplSourceObjectData<'tcx, N>),
|
||||
@ -487,7 +488,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||
pub fn nested_obligations(self) -> Vec<N> {
|
||||
match self {
|
||||
ImplSource::UserDefined(i) => i.nested,
|
||||
ImplSource::Param(n) => n,
|
||||
ImplSource::Param(n, _) => n,
|
||||
ImplSource::Builtin(i) => i.nested,
|
||||
ImplSource::AutoImpl(d) => d.nested,
|
||||
ImplSource::Closure(c) => c.nested,
|
||||
@ -502,7 +503,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||
pub fn borrow_nested_obligations(&self) -> &[N] {
|
||||
match &self {
|
||||
ImplSource::UserDefined(i) => &i.nested[..],
|
||||
ImplSource::Param(n) => &n[..],
|
||||
ImplSource::Param(n, _) => &n[..],
|
||||
ImplSource::Builtin(i) => &i.nested[..],
|
||||
ImplSource::AutoImpl(d) => &d.nested[..],
|
||||
ImplSource::Closure(c) => &c.nested[..],
|
||||
@ -524,7 +525,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||
substs: i.substs,
|
||||
nested: i.nested.into_iter().map(f).collect(),
|
||||
}),
|
||||
ImplSource::Param(n) => ImplSource::Param(n.into_iter().map(f).collect()),
|
||||
ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
|
||||
ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData {
|
||||
nested: i.nested.into_iter().map(f).collect(),
|
||||
}),
|
||||
|
@ -101,7 +101,7 @@ pub enum SelectionCandidate<'tcx> {
|
||||
/// `false` if there are no *further* obligations.
|
||||
has_nested: bool,
|
||||
},
|
||||
ParamCandidate(ty::PolyTraitRef<'tcx>),
|
||||
ParamCandidate(ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>),
|
||||
ImplCandidate(DefId),
|
||||
AutoImplCandidate(DefId),
|
||||
|
||||
|
@ -21,7 +21,9 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
|
||||
|
||||
super::ImplSource::Object(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::ImplSource::Param(ref n) => write!(f, "ImplSourceParamData({:?})", n),
|
||||
super::ImplSource::Param(ref n, ct) => {
|
||||
write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
|
||||
}
|
||||
|
||||
super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
|
@ -42,7 +42,9 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefPathHash, Definitions};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate};
|
||||
use rustc_hir::{
|
||||
Constness, HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate,
|
||||
};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
|
||||
@ -1635,6 +1637,8 @@ nop_list_lift! {projs; ProjectionKind => ProjectionKind}
|
||||
// This is the impl for `&'a InternalSubsts<'a>`.
|
||||
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
|
||||
|
||||
CloneLiftImpls! { for<'tcx> { Constness, } }
|
||||
|
||||
pub mod tls {
|
||||
use super::{ptr_eq, GlobalCtxt, TyCtxt};
|
||||
|
||||
|
@ -1503,9 +1503,11 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> Predicate<'tcx> {
|
||||
pub fn to_opt_poly_trait_ref(self) -> Option<PolyTraitRef<'tcx>> {
|
||||
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
|
||||
match self.skip_binders() {
|
||||
PredicateAtom::Trait(t, _) => Some(ty::Binder::bind(t.trait_ref)),
|
||||
PredicateAtom::Trait(t, constness) => {
|
||||
Some(ConstnessAnd { constness, value: ty::Binder::bind(t.trait_ref) })
|
||||
}
|
||||
PredicateAtom::Projection(..)
|
||||
| PredicateAtom::Subtype(..)
|
||||
| PredicateAtom::RegionOutlives(..)
|
||||
@ -1947,7 +1949,7 @@ impl<'tcx> ParamEnv<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
|
||||
pub struct ConstnessAnd<T> {
|
||||
pub constness: Constness,
|
||||
pub value: T,
|
||||
|
@ -1106,10 +1106,7 @@ impl<T> Binder<T> {
|
||||
|
||||
impl<T> Binder<Option<T>> {
|
||||
pub fn transpose(self) -> Option<Binder<T>> {
|
||||
match self.0 {
|
||||
Some(v) => Some(Binder(v)),
|
||||
None => None,
|
||||
}
|
||||
self.0.map(Binder)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, HirId, LangItem};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
|
||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::cast::CastTy;
|
||||
@ -11,9 +12,10 @@ use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{
|
||||
self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt, TypeAndMut,
|
||||
};
|
||||
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, TraitEngine};
|
||||
use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine};
|
||||
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
@ -765,9 +767,39 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
// Resolve a trait method call to its concrete implementation, which may be in a
|
||||
// `const` trait impl.
|
||||
if self.tcx.features().const_trait_impl {
|
||||
// Attempting to call a trait method?
|
||||
if let Some(trait_id) = tcx.trait_of_item(callee) {
|
||||
if !self.tcx.features().const_trait_impl {
|
||||
self.check_op(ops::FnCallNonConst(callee));
|
||||
return;
|
||||
}
|
||||
|
||||
let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
|
||||
let obligation = Obligation::new(
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
Binder::bind(TraitPredicate {
|
||||
trait_ref: TraitRef::from_method(tcx, trait_id, substs),
|
||||
}),
|
||||
);
|
||||
|
||||
let implsrc = tcx.infer_ctxt().enter(|infcx| {
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
selcx.select(&obligation).unwrap()
|
||||
});
|
||||
|
||||
// If the method is provided via a where-clause that does not use the `?const`
|
||||
// opt-out, the call is allowed.
|
||||
if let Some(ImplSource::Param(_, hir::Constness::Const)) = implsrc {
|
||||
debug!(
|
||||
"const_trait_impl: provided {:?} via where-clause in {:?}",
|
||||
trait_ref, param_env
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve a trait method call to its concrete implementation, which may be in a
|
||||
// `const` trait impl.
|
||||
let instance = Instance::resolve(tcx, param_env, callee, substs);
|
||||
debug!("Resolving ({:?}) -> {:?}", callee, instance);
|
||||
if let Ok(Some(func)) = instance {
|
||||
|
@ -12,7 +12,7 @@ use rustc_middle::mir::traversal;
|
||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{
|
||||
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef,
|
||||
Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
|
||||
Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable};
|
||||
@ -200,12 +200,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
|
||||
// Debuginfo can contain field projections, which count as a use of the base local. Skip
|
||||
// debuginfo so that we avoid the storage liveness assertion in that case.
|
||||
self.visit_source_info(&var_debug_info.source_info);
|
||||
}
|
||||
|
||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||
// This check is somewhat expensive, so only run it when -Zvalidate-mir is passed.
|
||||
if self.tcx.sess.opts.debugging_opts.validate_mir {
|
||||
|
@ -691,7 +691,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||
hir::ItemKind::GlobalAsm(..) => {}
|
||||
hir::ItemKind::OpaqueTy(..) => {
|
||||
// HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general)
|
||||
// Since rustdoc never need to do codegen and doesn't care about link-time reachability,
|
||||
// Since rustdoc never needs to do codegen and doesn't care about link-time reachability,
|
||||
// mark this as unreachable.
|
||||
// See https://github.com/rust-lang/rust/issues/75100
|
||||
if !self.tcx.sess.opts.actually_rustdoc {
|
||||
|
@ -143,7 +143,7 @@ impl<'a> Resolver<'a> {
|
||||
_ => {
|
||||
bug!(
|
||||
"GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
|
||||
DefKind::TyParam"
|
||||
DefKind::TyParam or DefKind::ConstParam"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2539,6 +2539,7 @@ impl<'a> Resolver<'a> {
|
||||
span: Span,
|
||||
all_ribs: &[Rib<'a>],
|
||||
) -> Res {
|
||||
const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation";
|
||||
debug!("validate_res_from_ribs({:?})", res);
|
||||
let ribs = &all_ribs[rib_index + 1..];
|
||||
|
||||
@ -2639,6 +2640,8 @@ impl<'a> Resolver<'a> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
self.session.delay_span_bug(span, CG_BUG_STR);
|
||||
return Res::Err;
|
||||
}
|
||||
}
|
||||
@ -2720,6 +2723,8 @@ impl<'a> Resolver<'a> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
self.session.delay_span_bug(span, CG_BUG_STR);
|
||||
return Res::Err;
|
||||
}
|
||||
|
||||
|
@ -350,11 +350,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
// Micro-optimization: filter out predicates relating to different traits.
|
||||
let matching_bounds =
|
||||
all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
|
||||
all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id());
|
||||
|
||||
// Keep only those bounds which may apply, and propagate overflow if it occurs.
|
||||
for bound in matching_bounds {
|
||||
let wc = self.evaluate_where_clause(stack, bound)?;
|
||||
let wc = self.evaluate_where_clause(stack, bound.value)?;
|
||||
if wc.may_apply() {
|
||||
candidates.vec.push(ParamCandidate(bound));
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::Constness;
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
|
||||
@ -55,8 +56,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
ParamCandidate(param) => {
|
||||
let obligations = self.confirm_param_candidate(obligation, param);
|
||||
Ok(ImplSource::Param(obligations))
|
||||
let obligations = self.confirm_param_candidate(obligation, param.value);
|
||||
Ok(ImplSource::Param(obligations, param.constness))
|
||||
}
|
||||
|
||||
ImplCandidate(impl_def_id) => {
|
||||
@ -70,7 +71,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
ProjectionCandidate(idx) => {
|
||||
let obligations = self.confirm_projection_candidate(obligation, idx)?;
|
||||
Ok(ImplSource::Param(obligations))
|
||||
// FIXME(jschievink): constness
|
||||
Ok(ImplSource::Param(obligations, Constness::NotConst))
|
||||
}
|
||||
|
||||
ObjectCandidate(idx) => {
|
||||
@ -106,7 +108,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// This indicates something like `Trait + Send: Send`. In this case, we know that
|
||||
// this holds because that's what the object type is telling us, and there's really
|
||||
// no additional obligations to prove and no types in particular to unify, etc.
|
||||
Ok(ImplSource::Param(Vec::new()))
|
||||
Ok(ImplSource::Param(Vec::new(), Constness::NotConst))
|
||||
}
|
||||
|
||||
BuiltinUnsizeCandidate => {
|
||||
@ -151,7 +153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
obligations.extend(self.infcx.commit_if_ok(|_| {
|
||||
self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate)
|
||||
.sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate.value)
|
||||
.map(|InferOk { obligations, .. }| obligations)
|
||||
.map_err(|_| Unimplemented)
|
||||
})?);
|
||||
|
@ -31,6 +31,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::Constness;
|
||||
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::fast_reject;
|
||||
@ -1335,7 +1336,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
(BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true,
|
||||
(_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false,
|
||||
|
||||
(ParamCandidate(..), ParamCandidate(..)) => false,
|
||||
(ParamCandidate(other), ParamCandidate(victim)) => {
|
||||
if other.value == victim.value && victim.constness == Constness::NotConst {
|
||||
// Drop otherwise equivalent non-const candidates in favor of const candidates.
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Global bounds from the where clause should be ignored
|
||||
// here (see issue #50825). Otherwise, we have a where
|
||||
@ -1354,11 +1362,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| TraitAliasCandidate(..)
|
||||
| ObjectCandidate(_)
|
||||
| ProjectionCandidate(_),
|
||||
) => !is_global(cand),
|
||||
) => !is_global(&cand.value),
|
||||
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
|
||||
// Prefer these to a global where-clause bound
|
||||
// (see issue #50825).
|
||||
is_global(cand)
|
||||
is_global(&cand.value)
|
||||
}
|
||||
(
|
||||
ImplCandidate(_)
|
||||
@ -1373,7 +1381,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) => {
|
||||
// Prefer these to a global where-clause bound
|
||||
// (see issue #50825).
|
||||
is_global(cand) && other.evaluation.must_apply_modulo_regions()
|
||||
is_global(&cand.value) && other.evaluation.must_apply_modulo_regions()
|
||||
}
|
||||
|
||||
(ProjectionCandidate(i), ProjectionCandidate(j))
|
||||
@ -2364,13 +2372,9 @@ impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
|
||||
type Item = &'o TraitObligationStack<'o, 'tcx>;
|
||||
|
||||
fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
|
||||
match self.head {
|
||||
Some(o) => {
|
||||
*self = o.previous;
|
||||
Some(o)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
let o = self.head?;
|
||||
*self = o.previous;
|
||||
Some(o)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,8 +498,8 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String>
|
||||
|
||||
for (p, _) in predicates {
|
||||
if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
|
||||
if Some(poly_trait_ref.def_id()) == sized_trait {
|
||||
types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder());
|
||||
if Some(poly_trait_ref.value.def_id()) == sized_trait {
|
||||
types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
|
||||
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
|
||||
pred.subst_supertrait(tcx, &trait_ref)
|
||||
.to_opt_poly_trait_ref()
|
||||
.map(|trait_ref| item.clone_and_push(trait_ref, *span))
|
||||
.map(|trait_ref| item.clone_and_push(trait_ref.value, *span))
|
||||
});
|
||||
debug!("expand_trait_aliases: items={:?}", items.clone());
|
||||
|
||||
@ -182,7 +182,7 @@ impl Iterator for SupertraitDefIds<'tcx> {
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
|
||||
.map(|trait_ref| trait_ref.def_id())
|
||||
.map(|trait_ref| trait_ref.value.def_id())
|
||||
.filter(|&super_def_id| visited.insert(super_def_id)),
|
||||
);
|
||||
Some(def_id)
|
||||
|
@ -294,7 +294,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||
let mut cause = cause.clone();
|
||||
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
|
||||
let derived_cause = traits::DerivedObligationCause {
|
||||
parent_trait_ref,
|
||||
parent_trait_ref: parent_trait_ref.value,
|
||||
parent_code: Rc::new(obligation.cause.code.clone()),
|
||||
};
|
||||
cause.make_mut().code =
|
||||
|
@ -1364,7 +1364,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|| {
|
||||
traits::transitive_bounds(
|
||||
tcx,
|
||||
predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
|
||||
predicates.iter().filter_map(|(p, _)| {
|
||||
p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value)
|
||||
}),
|
||||
)
|
||||
},
|
||||
|| param_name.to_string(),
|
||||
|
@ -810,10 +810,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// can be given the suggestion "u32::from(x) > y" rather than
|
||||
// "x > y.try_into().unwrap()".
|
||||
let lhs_expr_and_src = expected_ty_expr.and_then(|expr| {
|
||||
match self.tcx.sess.source_map().span_to_snippet(expr.span).ok() {
|
||||
Some(src) => Some((expr, src)),
|
||||
None => None,
|
||||
}
|
||||
self.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(expr.span)
|
||||
.ok()
|
||||
.map(|src| (expr, src))
|
||||
});
|
||||
let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
|
||||
(lhs_expr_and_src, exp_to_found_is_fallible)
|
||||
|
@ -1551,12 +1551,12 @@ where
|
||||
pred: F,
|
||||
inner: DrainFilterInner<'a, K, V>,
|
||||
}
|
||||
/// Most of the implementation of DrainFilter, independent of the type
|
||||
/// Most of the implementation of DrainFilter are generic over the type
|
||||
/// of the predicate, thus also serving for BTreeSet::DrainFilter.
|
||||
pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
|
||||
/// Reference to the length field in the borrowed map, updated live.
|
||||
length: &'a mut usize,
|
||||
/// Burried reference to the root field in the borrowed map.
|
||||
/// Buried reference to the root field in the borrowed map.
|
||||
/// Wrapped in `Option` to allow drop handler to `take` it.
|
||||
dormant_root: Option<DormantMutRef<'a, Root<K, V>>>,
|
||||
/// Contains a leaf edge preceding the next element to be returned, or the last leaf edge.
|
||||
|
@ -1486,7 +1486,7 @@ extern "rust-intrinsic" {
|
||||
/// let num_leading = unsafe { ctlz_nonzero(x) };
|
||||
/// assert_eq!(num_leading, 3);
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "constctlz", issue = "none")]
|
||||
#[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
|
||||
pub fn ctlz_nonzero<T: Copy>(x: T) -> T;
|
||||
|
||||
/// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
|
||||
|
@ -78,8 +78,6 @@
|
||||
#![feature(const_overflowing_int_methods)]
|
||||
#![feature(const_int_unchecked_arith)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_int_pow)]
|
||||
#![feature(constctlz)]
|
||||
#![feature(const_cttz)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(const_pin)]
|
||||
|
@ -791,7 +791,7 @@ $EndFeature, "
|
||||
```"),
|
||||
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -974,7 +974,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1340,7 +1340,7 @@ assert_eq!(3i8.wrapping_pow(6), -39);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1707,7 +1707,7 @@ assert_eq!(3i8.overflowing_pow(5), (-13, true));",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1757,7 +1757,7 @@ assert_eq!(x.pow(5), 32);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
|
@ -749,7 +749,7 @@ Basic usage:
|
||||
assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -865,7 +865,7 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1159,7 +1159,7 @@ Basic usage:
|
||||
assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1484,7 +1484,7 @@ Basic usage:
|
||||
assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1532,7 +1532,7 @@ Basic usage:
|
||||
", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1648,7 +1648,7 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
|
||||
// overflow cases it instead ends up returning the maximum value
|
||||
// of the type, and can return 0 for 0.
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
const fn one_less_than_next_power_of_two(self) -> Self {
|
||||
if self <= 1 { return 0; }
|
||||
|
||||
@ -1677,7 +1677,7 @@ Basic usage:
|
||||
assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
pub const fn next_power_of_two(self) -> Self {
|
||||
@ -1703,7 +1703,7 @@ $EndFeature, "
|
||||
```"),
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
pub const fn checked_next_power_of_two(self) -> Option<Self> {
|
||||
self.one_less_than_next_power_of_two().checked_add(1)
|
||||
}
|
||||
@ -1728,7 +1728,7 @@ $EndFeature, "
|
||||
```"),
|
||||
#[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
|
||||
reason = "needs decision on wrapping behaviour")]
|
||||
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||
pub const fn wrapping_next_power_of_two(self) -> Self {
|
||||
self.one_less_than_next_power_of_two().wrapping_add(1)
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_int_pow)]
|
||||
#![feature(wrapping_next_power_of_two)]
|
||||
|
||||
const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two();
|
||||
|
@ -0,0 +1,27 @@
|
||||
//! Basic test for calling methods on generic type parameters in `const fn`.
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct S;
|
||||
|
||||
impl const PartialEq for S {
|
||||
fn eq(&self, _: &S) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
||||
*t == *t
|
||||
}
|
||||
|
||||
const fn equals_self_wrapper<T: PartialEq>(t: &T) -> bool {
|
||||
equals_self(t)
|
||||
}
|
||||
|
||||
pub const EQ: bool = equals_self_wrapper(&S);
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,24 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_bound_opt_out)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct S;
|
||||
|
||||
impl const PartialEq for S {
|
||||
fn eq(&self, _: &S) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// This duplicate bound should not result in ambiguities. It should be equivalent to a single const
|
||||
// bound.
|
||||
const fn equals_self<T: PartialEq + ?const PartialEq>(t: &T) -> bool {
|
||||
*t == *t
|
||||
}
|
||||
|
||||
pub const EQ: bool = equals_self(&S);
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,11 @@
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_bound_opt_out)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub const fn equals_self<T: ?const PartialEq>(t: &T) -> bool {
|
||||
*t == *t
|
||||
//~^ ERROR calls in constant functions are limited to constant functions
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
--> $DIR/call-generic-method-fail.rs:7:5
|
||||
|
|
||||
LL | *t == *t
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
@ -0,0 +1,24 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_bound_opt_out)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct S;
|
||||
|
||||
impl PartialEq for S {
|
||||
fn eq(&self, _: &S) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const fn equals_self<T: ?const PartialEq>(t: &T) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub const EQ: bool = equals_self(&S);
|
||||
|
||||
// Calling `equals_self` with a type that only has a non-const impl is fine, because we opted out.
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,26 @@
|
||||
// FIXME(jschievink): this is not rejected correctly (only when the non-const impl is actually used)
|
||||
// ignore-test
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct S;
|
||||
|
||||
impl PartialEq for S {
|
||||
fn eq(&self, _: &S) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
// Calling `equals_self` with something that has a non-const impl should throw an error, despite
|
||||
// it not using the impl.
|
||||
|
||||
pub const EQ: bool = equals_self(&S);
|
||||
//~^ ERROR
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,23 @@
|
||||
//! Basic test for calling methods on generic type parameters in `const fn`.
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct S;
|
||||
|
||||
impl const PartialEq for S {
|
||||
fn eq(&self, _: &S) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
||||
*t == *t
|
||||
}
|
||||
|
||||
pub const EQ: bool = equals_self(&S);
|
||||
|
||||
fn main() {}
|
@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
||||
for &(p, _span) in preds {
|
||||
let p = p.subst(cx.tcx, subst);
|
||||
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
|
||||
if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() {
|
||||
if Some(trait_ref.value.def_id()) == cx.tcx.lang_items().future_trait() {
|
||||
is_future = true;
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user