Auto merge of #47630 - canndrew:exhaustive-patterns, r=nikomatsakis
Stabilise feature(never_type). Introduce feature(exhaustive_patterns) This stabilizes `!`, removing the feature gate as well as the old defaulting-to-`()` behavior. The pattern exhaustiveness checks which were covered by `feature(never_type)` have been moved behind a new `feature(exhaustive_patterns)` gate.
This commit is contained in:
commit
5ebf74851d
147 changed files with 296 additions and 548 deletions
|
|
@ -886,9 +886,8 @@ for ty::TypeVariants<'gcx>
|
|||
TyGeneratorWitness(types) => {
|
||||
types.hash_stable(hcx, hasher)
|
||||
}
|
||||
TyTuple(inner_tys, from_diverging_type_var) => {
|
||||
TyTuple(inner_tys) => {
|
||||
inner_tys.hash_stable(hcx, hasher);
|
||||
from_diverging_type_var.hash_stable(hcx, hasher);
|
||||
}
|
||||
TyProjection(ref projection_ty) => {
|
||||
projection_ty.hash_stable(hcx, hasher);
|
||||
|
|
|
|||
|
|
@ -609,12 +609,6 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
|
|||
bug!("encountered a canonical type during canonicalization")
|
||||
}
|
||||
|
||||
// Replace a `()` that "would've fallen back" to `!` with just `()`.
|
||||
ty::TyTuple(ref tys, true) => {
|
||||
assert!(tys.is_empty());
|
||||
self.tcx().mk_nil()
|
||||
}
|
||||
|
||||
ty::TyClosure(..)
|
||||
| ty::TyGenerator(..)
|
||||
| ty::TyGeneratorWitness(..)
|
||||
|
|
@ -634,7 +628,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
|
|||
| ty::TyFnPtr(_)
|
||||
| ty::TyDynamic(..)
|
||||
| ty::TyNever
|
||||
| ty::TyTuple(_, false)
|
||||
| ty::TyTuple(..)
|
||||
| ty::TyProjection(..)
|
||||
| ty::TyForeign(..)
|
||||
| ty::TyParam(..)
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
// get solved *here*.
|
||||
match fulfill_cx.select_all_or_error(self) {
|
||||
Ok(()) => (),
|
||||
Err(errors) => self.report_fulfillment_errors(&errors, None),
|
||||
Err(errors) => self.report_fulfillment_errors(&errors, None, false),
|
||||
}
|
||||
|
||||
implied_bounds
|
||||
|
|
|
|||
|
|
@ -173,12 +173,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx>
|
|||
ty::TyInfer(_) => {
|
||||
bug!("Unexpected type in full type resolver: {:?}", t);
|
||||
}
|
||||
ty::TyTuple(tys, true) => {
|
||||
// Un-default defaulted tuples - we are going to a
|
||||
// different infcx, and the default will just cause
|
||||
// pollution.
|
||||
self.tcx().intern_tup(tys, false)
|
||||
}
|
||||
_ => {
|
||||
t.super_fold_with(self)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
#![feature(match_default_bindings)]
|
||||
#![feature(macro_lifetime_matcher)]
|
||||
#![feature(macro_vis_matcher)]
|
||||
#![feature(never_type)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(non_exhaustive)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(proc_macro_internals)]
|
||||
|
|
|
|||
|
|
@ -151,13 +151,6 @@ declare_lint! {
|
|||
"lints that have been renamed or removed"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
|
||||
Deny,
|
||||
"attempt to resolve a trait on an expression whose type cannot be inferred but which \
|
||||
currently defaults to ()"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub SAFE_EXTERN_STATICS,
|
||||
Deny,
|
||||
|
|
@ -237,12 +230,6 @@ declare_lint! {
|
|||
"detect mut variables which don't need to be mutable"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub COERCE_NEVER,
|
||||
Deny,
|
||||
"detect coercion to !"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub SINGLE_USE_LIFETIME,
|
||||
Allow,
|
||||
|
|
@ -304,7 +291,6 @@ impl LintPass for HardwiredLints {
|
|||
INVALID_TYPE_PARAM_DEFAULT,
|
||||
CONST_ERR,
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
|
||||
SAFE_EXTERN_STATICS,
|
||||
SAFE_PACKED_BORROWS,
|
||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
|
|
@ -318,7 +304,6 @@ impl LintPass for HardwiredLints {
|
|||
DEPRECATED,
|
||||
UNUSED_UNSAFE,
|
||||
UNUSED_MUT,
|
||||
COERCE_NEVER,
|
||||
SINGLE_USE_LIFETIME,
|
||||
TYVAR_BEHIND_RAW_POINTER,
|
||||
ELIDED_LIFETIME_IN_PATH,
|
||||
|
|
|
|||
|
|
@ -1298,7 +1298,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||
PatKind::Tuple(ref subpats, ddpos) => {
|
||||
// (p1, ..., pN)
|
||||
let expected_len = match self.pat_ty(&pat)?.sty {
|
||||
ty::TyTuple(ref tys, _) => tys.len(),
|
||||
ty::TyTuple(ref tys) => tys.len(),
|
||||
ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
|
||||
};
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
let lhs_ty = lhs.ty(local_decls, tcx);
|
||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||
let ty = op.ty(tcx, lhs_ty, rhs_ty);
|
||||
tcx.intern_tup(&[ty, tcx.types.bool], false)
|
||||
tcx.intern_tup(&[ty, tcx.types.bool])
|
||||
}
|
||||
Rvalue::UnaryOp(UnOp::Not, ref operand) |
|
||||
Rvalue::UnaryOp(UnOp::Neg, ref operand) => {
|
||||
|
|
@ -178,10 +178,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
tcx.mk_array(ty, ops.len() as u64)
|
||||
}
|
||||
AggregateKind::Tuple => {
|
||||
tcx.mk_tup(
|
||||
ops.iter().map(|op| op.ty(local_decls, tcx)),
|
||||
false
|
||||
)
|
||||
tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx)))
|
||||
}
|
||||
AggregateKind::Adt(def, _, substs, _) => {
|
||||
tcx.type_of(def.did).subst(tcx, substs)
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ use syntax_pos::{DUMMY_SP, Span};
|
|||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn report_fulfillment_errors(&self,
|
||||
errors: &Vec<FulfillmentError<'tcx>>,
|
||||
body_id: Option<hir::BodyId>) {
|
||||
body_id: Option<hir::BodyId>,
|
||||
fallback_has_occurred: bool) {
|
||||
#[derive(Debug)]
|
||||
struct ErrorDescriptor<'tcx> {
|
||||
predicate: ty::Predicate<'tcx>,
|
||||
|
|
@ -107,7 +108,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
for (error, suppressed) in errors.iter().zip(is_suppressed) {
|
||||
if !suppressed {
|
||||
self.report_fulfillment_error(error, body_id);
|
||||
self.report_fulfillment_error(error, body_id, fallback_has_occurred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -151,11 +152,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>,
|
||||
body_id: Option<hir::BodyId>) {
|
||||
body_id: Option<hir::BodyId>,
|
||||
fallback_has_occurred: bool) {
|
||||
debug!("report_fulfillment_errors({:?})", error);
|
||||
match error.code {
|
||||
FulfillmentErrorCode::CodeSelectionError(ref e) => {
|
||||
self.report_selection_error(&error.obligation, e);
|
||||
self.report_selection_error(&error.obligation, e, fallback_has_occurred);
|
||||
}
|
||||
FulfillmentErrorCode::CodeProjectionError(ref e) => {
|
||||
self.report_projection_error(&error.obligation, e);
|
||||
|
|
@ -533,7 +535,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
pub fn report_selection_error(&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &SelectionError<'tcx>)
|
||||
error: &SelectionError<'tcx>,
|
||||
fallback_has_occurred: bool)
|
||||
{
|
||||
let span = obligation.cause.span;
|
||||
|
||||
|
|
@ -619,6 +622,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.report_similar_impl_candidates(impl_candidates, &mut err);
|
||||
}
|
||||
|
||||
// If this error is due to `!: Trait` not implemented but `(): Trait` is
|
||||
// implemented, and fallback has occured, then it could be due to a
|
||||
// variable that used to fallback to `()` now falling back to `!`. Issue a
|
||||
// note informing about the change in behaviour.
|
||||
if trait_predicate.skip_binder().self_ty().is_never()
|
||||
&& fallback_has_occurred
|
||||
{
|
||||
let predicate = trait_predicate.map_bound(|mut trait_pred| {
|
||||
{
|
||||
let trait_ref = &mut trait_pred.trait_ref;
|
||||
let never_substs = trait_ref.substs;
|
||||
let mut unit_substs = Vec::with_capacity(never_substs.len());
|
||||
unit_substs.push(self.tcx.mk_nil().into());
|
||||
unit_substs.extend(&never_substs[1..]);
|
||||
trait_ref.substs = self.tcx.intern_substs(&unit_substs);
|
||||
}
|
||||
trait_pred
|
||||
});
|
||||
let unit_obligation = Obligation {
|
||||
predicate: ty::Predicate::Trait(predicate),
|
||||
.. obligation.clone()
|
||||
};
|
||||
let mut selcx = SelectionContext::new(self);
|
||||
if selcx.evaluate_obligation(&unit_obligation) {
|
||||
err.note("the trait is implemented for `()`. \
|
||||
Possibly this error has been caused by changes to \
|
||||
Rust's type-inference algorithm \
|
||||
(see: https://github.com/rust-lang/rust/issues/48950 \
|
||||
for more info). Consider whether you meant to use the \
|
||||
type `()` here instead.");
|
||||
}
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
|
|
@ -729,14 +765,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}).map(|sp| self.tcx.sess.codemap().def_span(sp)); // the sp could be an fn def
|
||||
|
||||
let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
|
||||
ty::TyTuple(ref tys, _) => tys.iter()
|
||||
ty::TyTuple(ref tys) => tys.iter()
|
||||
.map(|_| ArgKind::empty()).collect::<Vec<_>>(),
|
||||
_ => vec![ArgKind::empty()],
|
||||
};
|
||||
let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
|
||||
ty::TyTuple(ref tys, _) => tys.iter()
|
||||
ty::TyTuple(ref tys) => tys.iter()
|
||||
.map(|t| match t.sty {
|
||||
ty::TypeVariants::TyTuple(ref tys, _) => ArgKind::Tuple(
|
||||
ty::TypeVariants::TyTuple(ref tys) => ArgKind::Tuple(
|
||||
Some(span),
|
||||
tys.iter()
|
||||
.map(|ty| ("_".to_owned(), format!("{}", ty.sty)))
|
||||
|
|
@ -986,7 +1022,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
|
||||
trait_ref: &ty::TraitRef<'tcx>) -> String {
|
||||
let inputs = trait_ref.substs.type_at(1);
|
||||
let sig = if let ty::TyTuple(inputs, _) = inputs.sty {
|
||||
let sig = if let ty::TyTuple(inputs) = inputs.sty {
|
||||
tcx.mk_fn_sig(
|
||||
inputs.iter().map(|&x| x),
|
||||
tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
|
||||
|
|
@ -1422,7 +1458,7 @@ impl ArgKind {
|
|||
/// argument. This has no name (`_`) and no source spans..
|
||||
pub fn from_expected_ty(t: Ty<'_>) -> ArgKind {
|
||||
match t.sty {
|
||||
ty::TyTuple(ref tys, _) => ArgKind::Tuple(
|
||||
ty::TyTuple(ref tys) => ArgKind::Tuple(
|
||||
None,
|
||||
tys.iter()
|
||||
.map(|ty| ("_".to_owned(), format!("{}", ty.sty)))
|
||||
|
|
|
|||
|
|
@ -330,11 +330,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
|||
if data.is_global() {
|
||||
// no type variables present, can use evaluation for better caching.
|
||||
// FIXME: consider caching errors too.
|
||||
if
|
||||
// make defaulted unit go through the slow path for better warnings,
|
||||
// please remove this when the warnings are removed.
|
||||
!trait_obligation.predicate.skip_binder().self_ty().is_defaulted_unit() &&
|
||||
selcx.evaluate_obligation_conservatively(&obligation) {
|
||||
if selcx.evaluate_obligation_conservatively(&obligation) {
|
||||
debug!("selecting trait `{:?}` at depth {} evaluated to holds",
|
||||
data, obligation.recursion_depth);
|
||||
return Ok(Some(vec![]))
|
||||
|
|
|
|||
|
|
@ -580,7 +580,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(errors) => {
|
||||
infcx.report_fulfillment_errors(&errors, None);
|
||||
infcx.report_fulfillment_errors(&errors, None, false);
|
||||
// An unnormalized env is better than nothing.
|
||||
return elaborated_env;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ fn trivial_dropck_outlives<'cx, 'tcx>(tcx: TyCtxt<'cx, '_, 'tcx>, ty: Ty<'tcx>)
|
|||
|
||||
// (T1..Tn) and closures have same properties as T1..Tn --
|
||||
// check if *any* of those are trivial.
|
||||
ty::TyTuple(ref tys, _) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)),
|
||||
ty::TyTuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)),
|
||||
ty::TyClosure(def_id, ref substs) => substs
|
||||
.upvar_tys(def_id, tcx)
|
||||
.all(|t| trivial_dropck_outlives(tcx, t)),
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ use std::mem;
|
|||
use std::rc::Rc;
|
||||
use syntax::abi::Abi;
|
||||
use hir;
|
||||
use lint;
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
|
||||
|
||||
|
|
@ -526,54 +525,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
debug!("select({:?})", obligation);
|
||||
assert!(!obligation.predicate.has_escaping_regions());
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
||||
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
|
||||
let ret = match self.candidate_from_obligation(&stack)? {
|
||||
None => None,
|
||||
Some(candidate) => Some(self.confirm_candidate(obligation, candidate)?)
|
||||
};
|
||||
|
||||
// Test whether this is a `()` which was produced by defaulting a
|
||||
// diverging type variable with `!` disabled. If so, we may need
|
||||
// to raise a warning.
|
||||
if obligation.predicate.skip_binder().self_ty().is_defaulted_unit() {
|
||||
let mut raise_warning = true;
|
||||
// Don't raise a warning if the trait is implemented for ! and only
|
||||
// permits a trivial implementation for !. This stops us warning
|
||||
// about (for example) `(): Clone` becoming `!: Clone` because such
|
||||
// a switch can't cause code to stop compiling or execute
|
||||
// differently.
|
||||
let mut never_obligation = obligation.clone();
|
||||
let def_id = never_obligation.predicate.skip_binder().trait_ref.def_id;
|
||||
never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| {
|
||||
// Swap out () with ! so we can check if the trait is impld for !
|
||||
{
|
||||
let trait_ref = &mut trait_pred.trait_ref;
|
||||
let unit_substs = trait_ref.substs;
|
||||
let mut never_substs = Vec::with_capacity(unit_substs.len());
|
||||
never_substs.push(tcx.types.never.into());
|
||||
never_substs.extend(&unit_substs[1..]);
|
||||
trait_ref.substs = tcx.intern_substs(&never_substs);
|
||||
}
|
||||
trait_pred
|
||||
});
|
||||
if let Ok(Some(..)) = self.select(&never_obligation) {
|
||||
if !tcx.trait_relevant_for_never(def_id) {
|
||||
// The trait is also implemented for ! and the resulting
|
||||
// implementation cannot actually be invoked in any way.
|
||||
raise_warning = false;
|
||||
}
|
||||
}
|
||||
|
||||
if raise_warning {
|
||||
tcx.lint_node(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
|
||||
obligation.cause.body_id,
|
||||
obligation.cause.span,
|
||||
&format!("code relies on type inference rules which are likely \
|
||||
to change"));
|
||||
}
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
|
|
@ -1929,7 +1886,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
// (.., T) -> (.., U).
|
||||
(&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => {
|
||||
(&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => {
|
||||
tys_a.len() == tys_b.len()
|
||||
}
|
||||
|
||||
|
|
@ -2068,7 +2025,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
|
||||
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never,
|
||||
|
||||
ty::TyTuple(tys, _) => {
|
||||
ty::TyTuple(tys) => {
|
||||
Where(ty::Binder(tys.last().into_iter().cloned().collect()))
|
||||
}
|
||||
|
||||
|
|
@ -2122,7 +2079,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
Where(ty::Binder(vec![element_ty]))
|
||||
}
|
||||
|
||||
ty::TyTuple(tys, _) => {
|
||||
ty::TyTuple(tys) => {
|
||||
// (*) binder moved here
|
||||
Where(ty::Binder(tys.to_vec()))
|
||||
}
|
||||
|
|
@ -2215,7 +2172,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
vec![element_ty]
|
||||
}
|
||||
|
||||
ty::TyTuple(ref tys, _) => {
|
||||
ty::TyTuple(ref tys) => {
|
||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||
tys.to_vec()
|
||||
}
|
||||
|
|
@ -3004,7 +2961,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
// (.., T) -> (.., U).
|
||||
(&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => {
|
||||
(&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => {
|
||||
assert_eq!(tys_a.len(), tys_b.len());
|
||||
|
||||
// The last field of the tuple has to exist.
|
||||
|
|
@ -3017,7 +2974,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
|
||||
// Check that the source tuple with the target's
|
||||
// last element is equal to the target.
|
||||
let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false);
|
||||
let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)));
|
||||
let InferOk { obligations, .. } =
|
||||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.eq(target, new_tuple)
|
||||
|
|
|
|||
|
|
@ -503,7 +503,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
let arguments_tuple = match tuple_arguments {
|
||||
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
|
||||
TupleArgumentsFlag::Yes =>
|
||||
self.intern_tup(sig.skip_binder().inputs(), false),
|
||||
self.intern_tup(sig.skip_binder().inputs()),
|
||||
};
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: fn_trait_def_id,
|
||||
|
|
|
|||
|
|
@ -2014,7 +2014,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
|
||||
let converted_sig = sig.map_bound(|s| {
|
||||
let params_iter = match s.inputs()[0].sty {
|
||||
ty::TyTuple(params, _) => {
|
||||
ty::TyTuple(params) => {
|
||||
params.into_iter().cloned()
|
||||
}
|
||||
_ => bug!(),
|
||||
|
|
@ -2134,25 +2134,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
self.mk_ty(TySlice(ty))
|
||||
}
|
||||
|
||||
pub fn intern_tup(self, ts: &[Ty<'tcx>], defaulted: bool) -> Ty<'tcx> {
|
||||
self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted))
|
||||
pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
|
||||
self.mk_ty(TyTuple(self.intern_type_list(ts)))
|
||||
}
|
||||
|
||||
pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I,
|
||||
defaulted: bool) -> I::Output {
|
||||
iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted)))
|
||||
pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts))))
|
||||
}
|
||||
|
||||
pub fn mk_nil(self) -> Ty<'tcx> {
|
||||
self.intern_tup(&[], false)
|
||||
}
|
||||
|
||||
pub fn mk_diverging_default(self) -> Ty<'tcx> {
|
||||
if self.features().never_type {
|
||||
self.types.never
|
||||
} else {
|
||||
self.intern_tup(&[], true)
|
||||
}
|
||||
self.intern_tup(&[])
|
||||
}
|
||||
|
||||
pub fn mk_bool(self) -> Ty<'tcx> {
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
|
|||
match self.sty {
|
||||
ty::TyBool | ty::TyChar | ty::TyInt(_) |
|
||||
ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
|
||||
ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
|
||||
ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
|
||||
|
||||
ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
|
||||
ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len()))
|
||||
}
|
||||
ty::TyNever => Some(NeverSimplifiedType),
|
||||
ty::TyTuple(ref tys, _) => {
|
||||
ty::TyTuple(ref tys) => {
|
||||
Some(TupleSimplifiedType(tys.len()))
|
||||
}
|
||||
ty::TyFnPtr(ref f) => {
|
||||
|
|
|
|||
|
|
@ -179,10 +179,7 @@ impl FlagComputation {
|
|||
self.add_ty(m.ty);
|
||||
}
|
||||
|
||||
&ty::TyTuple(ref ts, is_default) => {
|
||||
if is_default {
|
||||
self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX);
|
||||
}
|
||||
&ty::TyTuple(ref ts) => {
|
||||
self.add_tys(&ts[..]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
},
|
||||
|
||||
TyNever => DefIdForest::full(tcx),
|
||||
TyTuple(ref tys, _) => {
|
||||
TyTuple(ref tys) => {
|
||||
DefIdForest::union(tcx, tys.iter().map(|ty| {
|
||||
ty.uninhabited_from(visited, tcx)
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -355,9 +355,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
|
|||
ty::TyRawPtr(mt) |
|
||||
ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty),
|
||||
|
||||
ty::TyTuple(ref tys, _) => tys.iter()
|
||||
.filter_map(|ty| characteristic_def_id_of_type(ty))
|
||||
.next(),
|
||||
ty::TyTuple(ref tys) => tys.iter()
|
||||
.filter_map(|ty| characteristic_def_id_of_type(ty))
|
||||
.next(),
|
||||
|
||||
ty::TyFnDef(def_id, _) |
|
||||
ty::TyClosure(def_id, _) |
|
||||
|
|
|
|||
|
|
@ -1318,7 +1318,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||
StructKind::AlwaysSized)?
|
||||
}
|
||||
|
||||
ty::TyTuple(tys, _) => {
|
||||
ty::TyTuple(tys) => {
|
||||
let kind = if tys.len() == 0 {
|
||||
StructKind::AlwaysSized
|
||||
} else {
|
||||
|
|
@ -2243,7 +2243,7 @@ impl<'a, 'tcx> TyLayout<'tcx> {
|
|||
substs.field_tys(def_id, tcx).nth(i).unwrap()
|
||||
}
|
||||
|
||||
ty::TyTuple(tys, _) => tys[i],
|
||||
ty::TyTuple(tys) => tys[i],
|
||||
|
||||
// SIMD vector types.
|
||||
ty::TyAdt(def, ..) if def.repr.simd() => {
|
||||
|
|
|
|||
|
|
@ -2046,7 +2046,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
vec![ty]
|
||||
}
|
||||
|
||||
TyTuple(ref tys, _) => {
|
||||
TyTuple(ref tys) => {
|
||||
match tys.last() {
|
||||
None => vec![],
|
||||
Some(ty) => self.sized_constraint_for_ty(tcx, ty)
|
||||
|
|
|
|||
|
|
@ -529,11 +529,10 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
|||
Ok(tcx.mk_slice(t))
|
||||
}
|
||||
|
||||
(&ty::TyTuple(as_, a_defaulted), &ty::TyTuple(bs, b_defaulted)) =>
|
||||
(&ty::TyTuple(as_), &ty::TyTuple(bs)) =>
|
||||
{
|
||||
if as_.len() == bs.len() {
|
||||
let defaulted = a_defaulted || b_defaulted;
|
||||
Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)), defaulted)?)
|
||||
Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?)
|
||||
} else if !(as_.is_empty() || bs.is_empty()) {
|
||||
Err(TypeError::TupleSize(
|
||||
expected_found(relation, &as_.len(), &bs.len())))
|
||||
|
|
|
|||
|
|
@ -869,7 +869,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
|||
ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
|
||||
ty::TyDynamic(ref trait_ty, ref region) =>
|
||||
ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
|
||||
ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
|
||||
ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
|
||||
ty::TyFnDef(def_id, substs) => {
|
||||
ty::TyFnDef(def_id, substs.fold_with(folder))
|
||||
}
|
||||
|
|
@ -908,7 +908,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
|||
ty::TyAdt(_, substs) => substs.visit_with(visitor),
|
||||
ty::TyDynamic(ref trait_ty, ref reg) =>
|
||||
trait_ty.visit_with(visitor) || reg.visit_with(visitor),
|
||||
ty::TyTuple(ts, _) => ts.visit_with(visitor),
|
||||
ty::TyTuple(ts) => ts.visit_with(visitor),
|
||||
ty::TyFnDef(_, substs) => substs.visit_with(visitor),
|
||||
ty::TyFnPtr(ref f) => f.visit_with(visitor),
|
||||
ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
|
||||
|
|
|
|||
|
|
@ -148,11 +148,7 @@ pub enum TypeVariants<'tcx> {
|
|||
TyNever,
|
||||
|
||||
/// A tuple type. For example, `(i32, bool)`.
|
||||
/// The bool indicates whether this is a unit tuple and was created by
|
||||
/// defaulting a diverging type variable with feature(never_type) disabled.
|
||||
/// It's only purpose is for raising future-compatibility warnings for when
|
||||
/// diverging type variables start defaulting to ! instead of ().
|
||||
TyTuple(&'tcx Slice<Ty<'tcx>>, bool),
|
||||
TyTuple(&'tcx Slice<Ty<'tcx>>),
|
||||
|
||||
/// The projection of an associated type. For example,
|
||||
/// `<T as Trait<..>>::N`.
|
||||
|
|
@ -1274,7 +1270,7 @@ impl RegionKind {
|
|||
impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
pub fn is_nil(&self) -> bool {
|
||||
match self.sty {
|
||||
TyTuple(ref tys, _) => tys.is_empty(),
|
||||
TyTuple(ref tys) => tys.is_empty(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
@ -1286,15 +1282,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Test whether this is a `()` which was produced by defaulting a
|
||||
/// diverging type variable with feature(never_type) disabled.
|
||||
pub fn is_defaulted_unit(&self) -> bool {
|
||||
match self.sty {
|
||||
TyTuple(_, true) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_primitive(&self) -> bool {
|
||||
match self.sty {
|
||||
TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true,
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
// Don't use `non_enum_variant`, this may be a univariant enum.
|
||||
adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
|
||||
}
|
||||
(&TyTuple(ref v, _), None) => v.get(i).cloned(),
|
||||
(&TyTuple(ref v), None) => v.get(i).cloned(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ty::TyTuple(tys, _) => {
|
||||
ty::TyTuple(tys) => {
|
||||
if let Some((&last_ty, _)) = tys.split_last() {
|
||||
ty = last_ty;
|
||||
} else {
|
||||
|
|
@ -344,7 +344,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
break;
|
||||
}
|
||||
},
|
||||
(&TyTuple(a_tys, _), &TyTuple(b_tys, _))
|
||||
(&TyTuple(a_tys), &TyTuple(b_tys))
|
||||
if a_tys.len() == b_tys.len() => {
|
||||
if let Some(a_last) = a_tys.last() {
|
||||
a = a_last;
|
||||
|
|
@ -709,9 +709,8 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
|
|||
TyGeneratorWitness(tys) => {
|
||||
self.hash(tys.skip_binder().len());
|
||||
}
|
||||
TyTuple(tys, defaulted) => {
|
||||
TyTuple(tys) => {
|
||||
self.hash(tys.len());
|
||||
self.hash(defaulted);
|
||||
}
|
||||
TyParam(p) => {
|
||||
self.hash(p.idx);
|
||||
|
|
@ -838,7 +837,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
|||
-> Representability
|
||||
{
|
||||
match ty.sty {
|
||||
TyTuple(ref ts, _) => {
|
||||
TyTuple(ref ts) => {
|
||||
// Find non representable
|
||||
fold_repr(ts.iter().map(|ty| {
|
||||
is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
|
||||
|
|
@ -1106,7 +1105,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// state transformation pass
|
||||
ty::TyGenerator(..) => true,
|
||||
|
||||
ty::TyTuple(ref tys, _) => tys.iter().cloned().any(needs_drop),
|
||||
ty::TyTuple(ref tys) => tys.iter().cloned().any(needs_drop),
|
||||
|
||||
// unions don't have destructors regardless of the child types
|
||||
ty::TyAdt(def, _) if def.is_union() => false,
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
|
|||
ty::TyGeneratorWitness(ts) => {
|
||||
stack.extend(ts.skip_binder().iter().cloned().rev());
|
||||
}
|
||||
ty::TyTuple(ts, _) => {
|
||||
ty::TyTuple(ts) => {
|
||||
stack.extend(ts.iter().cloned().rev());
|
||||
}
|
||||
ty::TyFnDef(_, substs) => {
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
|||
self.compute_const(len);
|
||||
}
|
||||
|
||||
ty::TyTuple(ref tys, _) => {
|
||||
ty::TyTuple(ref tys) => {
|
||||
if let Some((_last, rest)) = tys.split_last() {
|
||||
for elem in rest {
|
||||
self.require_sized(elem, traits::TupleElem);
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ impl PrintContext {
|
|||
|
||||
if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
|
||||
let projection_ty = projections[0].ty;
|
||||
if let TyTuple(ref args, _) = substs.type_at(1).sty {
|
||||
if let TyTuple(ref args) = substs.type_at(1).sty {
|
||||
return self.fn_sig(f, args, false, projection_ty);
|
||||
}
|
||||
}
|
||||
|
|
@ -1013,7 +1013,7 @@ define_print! {
|
|||
tm.print(f, cx)
|
||||
}
|
||||
TyNever => write!(f, "!"),
|
||||
TyTuple(ref tys, _) => {
|
||||
TyTuple(ref tys) => {
|
||||
write!(f, "(")?;
|
||||
let mut tys = tys.iter();
|
||||
if let Some(&ty) = tys.next() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue