Use Term in ProjectionPredicate

ProjectionPredicate should be able to handle both associated types and consts so this adds the
first step of that. It mainly just pipes types all the way down, not entirely sure how to handle
consts, but hopefully that'll come with time.
This commit is contained in:
kadmin 2022-01-08 09:28:12 +00:00
parent fb57b7518d
commit 67f56671d0
51 changed files with 274 additions and 259 deletions

View File

@ -335,7 +335,7 @@ dependencies = [
"cargo-test-macro",
"cargo-test-support",
"cargo-util",
"clap 3.0.6",
"clap",
"crates-io",
"crossbeam-utils",
"curl",
@ -615,28 +615,13 @@ dependencies = [
"ansi_term 0.12.1",
"atty",
"bitflags",
"strsim 0.8.0",
"textwrap 0.11.0",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
"yaml-rust 0.3.5",
]
[[package]]
name = "clap"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1957aa4a5fb388f0a0a73ce7556c5b42025b874e5cdc2c670775e346e97adec0"
dependencies = [
"atty",
"bitflags",
"indexmap",
"os_str_bytes",
"strsim 0.10.0",
"termcolor",
"textwrap 0.14.2",
]
[[package]]
name = "clippy"
version = "0.1.60"
@ -669,7 +654,7 @@ version = "0.0.1"
dependencies = [
"bytecount",
"cargo_metadata 0.14.0",
"clap 2.34.0",
"clap",
"indoc",
"itertools 0.10.1",
"opener",
@ -1751,7 +1736,7 @@ name = "installer"
version = "0.0.0"
dependencies = [
"anyhow",
"clap 2.34.0",
"clap",
"flate2",
"lazy_static",
"num_cpus",
@ -2190,7 +2175,7 @@ dependencies = [
"ammonia",
"anyhow",
"chrono",
"clap 2.34.0",
"clap",
"elasticlunr-rs",
"env_logger 0.7.1",
"handlebars",
@ -2521,15 +2506,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "os_str_bytes"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
dependencies = [
"memchr",
]
[[package]]
name = "output_vt100"
version = "0.1.2"
@ -2934,7 +2910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0b4b5faaf07040474e8af74a9e19ff167d5d204df5db5c5c765edecfb900358"
dependencies = [
"bitflags",
"clap 2.34.0",
"clap",
"derive_more",
"env_logger 0.7.1",
"humantime 2.0.1",
@ -3282,7 +3258,7 @@ dependencies = [
name = "rustbook"
version = "0.1.0"
dependencies = [
"clap 2.34.0",
"clap",
"env_logger 0.7.1",
"mdbook",
]
@ -4898,19 +4874,13 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "structopt"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c"
dependencies = [
"clap 2.34.0",
"clap",
"lazy_static",
"structopt-derive",
]
@ -5081,12 +5051,6 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "textwrap"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
[[package]]
name = "thiserror"
version = "1.0.30"

View File

@ -997,10 +997,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
let kind = match constraint.kind {
AssocConstraintKind::Equality { ref term } => match term {
Term::Ty(ref ty) => hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) },
Term::Const(ref c) => hir::TypeBindingKind::Const { c: self.lower_anon_const(c) },
},
AssocConstraintKind::Equality { ref term } => {
let term = match term {
Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(),
Term::Const(ref c) => self.lower_anon_const(c).into(),
};
hir::TypeBindingKind::Equality { term }
}
AssocConstraintKind::Bound { ref bounds } => {
let mut capturable_lifetimes;
let mut parent_def_id = self.current_hir_id_owner;
@ -1079,7 +1082,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
itctx,
);
hir::TypeBindingKind::Equality { ty }
hir::TypeBindingKind::Equality { term: ty.into() }
})
} else {
// Desugar `AssocTy: Bounds` into a type binding where the

View File

@ -420,7 +420,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ty: &'hir hir::Ty<'hir>,
) -> hir::TypeBinding<'hir> {
let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME);
let kind = hir::TypeBindingKind::Equality { ty };
let kind = hir::TypeBindingKind::Equality { term: ty.into() };
let args = arena_vec![self;];
let bindings = arena_vec![self;];
let gen_args = self.arena.alloc(hir::GenericArgs {

View File

@ -964,9 +964,7 @@ impl<'a> State<'a> {
Term::Const(c) => self.print_expr_anon_const(c),
}
}
ast::AssocConstraintKind::Bound { bounds } => {
self.print_type_bounds(":", &*bounds);
}
ast::AssocConstraintKind::Bound { bounds } => self.print_type_bounds(":", &*bounds),
}
}

View File

@ -779,7 +779,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
[
hir::TypeBinding {
ident: Ident { name: sym::Output, .. },
kind: hir::TypeBindingKind::Equality { ty },
kind:
hir::TypeBindingKind::Equality {
term: hir::Term::Ty(ty),
},
..
},
],

View File

@ -377,7 +377,7 @@ impl GenericArgs<'_> {
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err),
_ => false,
}) || self.bindings.iter().any(|arg| match arg.kind {
TypeBindingKind::Equality { ty } => matches!(ty.kind, TyKind::Err),
TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err),
_ => false,
})
}
@ -2129,21 +2129,37 @@ pub struct TypeBinding<'hir> {
pub span: Span,
}
#[derive(Debug, HashStable_Generic)]
pub enum Term<'hir> {
Ty(&'hir Ty<'hir>),
Const(AnonConst),
}
impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
fn from(ty: &'hir Ty<'hir>) -> Self {
Term::Ty(ty)
}
}
impl<'hir> From<AnonConst> for Term<'hir> {
fn from(c: AnonConst) -> Self {
Term::Const(c)
}
}
// Represents the two kinds of type bindings.
#[derive(Debug, HashStable_Generic)]
pub enum TypeBindingKind<'hir> {
/// E.g., `Foo<Bar: Send>`.
Constraint { bounds: &'hir [GenericBound<'hir>] },
/// E.g., `Foo<Bar = ()>`.
Equality { ty: &'hir Ty<'hir> },
/// E.g., `Foo<N = 3>`.
Const { c: AnonConst },
/// E.g., `Foo<Bar = ()>`, `Foo<Bar = ()>`
Equality { term: Term<'hir> },
}
impl TypeBinding<'_> {
pub fn ty(&self) -> &Ty<'_> {
match self.kind {
TypeBindingKind::Equality { ref ty } => ty,
TypeBindingKind::Equality { term: Term::Ty(ref ty) } => ty,
_ => panic!("expected equality type binding for parenthesized generic args"),
}
}

View File

@ -827,11 +827,11 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
visitor.visit_ident(type_binding.ident);
visitor.visit_generic_args(type_binding.span, type_binding.gen_args);
match type_binding.kind {
TypeBindingKind::Equality { ref ty } => visitor.visit_ty(ty),
TypeBindingKind::Const { ref c } => visitor.visit_anon_const(c),
TypeBindingKind::Constraint { bounds } => {
walk_list!(visitor, visit_param_bound, bounds);
}
TypeBindingKind::Equality { ref term } => match term {
Term::Ty(ref ty) => visitor.visit_ty(ty),
Term::Const(ref c) => visitor.visit_anon_const(c),
},
TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds),
}
}

View File

@ -6,7 +6,7 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
@ -1752,13 +1752,12 @@ impl<'a> State<'a> {
self.print_generic_args(binding.gen_args, false, false);
self.space();
match generic_args.bindings[0].kind {
hir::TypeBindingKind::Equality { ref ty } => {
hir::TypeBindingKind::Equality { ref term } => {
self.word_space("=");
self.print_type(ty);
}
hir::TypeBindingKind::Const { ref c } => {
self.word_space("=");
self.print_anon_const(c);
match term {
Term::Ty(ref ty) => self.print_type(ty),
Term::Const(ref c) => self.print_anon_const(c),
}
}
hir::TypeBindingKind::Constraint { bounds } => {
self.print_bounds(":", bounds);

View File

@ -69,7 +69,7 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{
self,
subst::{GenericArgKind, Subst, SubstsRef},
Region, Ty, TyCtxt, TypeFoldable,
Region, Term, Ty, TyCtxt, TypeFoldable,
};
use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span};
use rustc_target::spec::abi;
@ -1780,7 +1780,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
{
if projection_predicate.projection_ty.item_def_id == item_def_id {
// We don't account for multiple `Future::Output = Ty` contraints.
return Some(projection_predicate.ty);
match projection_predicate.term {
Term::Ty(ty) => return Some(ty),
// Can return None, but not sure if that makes sense?
Term::Const(_c) => todo!(),
}
}
}
}

View File

@ -122,8 +122,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
{
for type_binding in generic_args.bindings.iter() {
if type_binding.ident.name == rustc_span::sym::Output {
if let hir::TypeBindingKind::Equality { ty } =
type_binding.kind
if let hir::TypeBindingKind::Equality {
term: hir::Term::Ty(ty),
} = type_binding.kind
{
return Some(ty);
}

View File

@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::subst::{GenericArgKind, Subst};
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor};
use rustc_middle::ty::{self, OpaqueTypeKey, Term, Ty, TyCtxt, TypeFoldable, TypeVisitor};
use rustc_span::Span;
use std::ops::ControlFlow;
@ -584,9 +584,13 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
debug!(?predicate);
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
if projection.ty.references_error() {
// No point on adding these obligations since there's a type error involved.
return tcx.ty_error();
if let Term::Ty(ty) = projection.term {
if ty.references_error() {
// No point on adding these obligations since there's a type error involved.
return tcx.ty_error();
}
} else {
todo!();
}
}

View File

@ -26,7 +26,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
kind: TypeVariableOriginKind::NormalizeProjectionType,
span: self.tcx.def_span(def_id),
});
let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
let projection =
ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, term: ty_var.into() });
let obligation = Obligation::with_depth(
cause,
recursion_depth,

View File

@ -1,5 +1,5 @@
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, InferConst, Ty, TypeFlags};
use crate::ty::{self, InferConst, Term, Ty, TypeFlags};
use std::slice;
#[derive(Debug)]
@ -241,9 +241,12 @@ impl FlagComputation {
self.add_ty(a);
self.add_ty(b);
}
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
self.add_projection_ty(projection_ty);
self.add_ty(ty);
match term {
Term::Ty(ty) => self.add_ty(ty),
Term::Const(_c) => todo!(),
}
}
ty::PredicateKind::WellFormed(arg) => {
self.add_substs(slice::from_ref(&arg));

View File

@ -484,7 +484,7 @@ crate struct PredicateInner<'tcx> {
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(PredicateInner<'_>, 48);
static_assert_size!(PredicateInner<'_>, 56);
#[derive(Clone, Copy, Lift)]
pub struct Predicate<'tcx> {
@ -795,11 +795,35 @@ pub struct CoercePredicate<'tcx> {
}
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub enum Term<'tcx> {
Ty(Ty<'tcx>),
Const(&'tcx Const<'tcx>),
}
impl<'tcx> From<Ty<'tcx>> for Term<'tcx> {
fn from(ty: Ty<'tcx>) -> Self {
Term::Ty(ty)
}
}
impl<'tcx> From<&'tcx Const<'tcx>> for Term<'tcx> {
fn from(c: &'tcx Const<'tcx>) -> Self {
Term::Const(c)
}
}
impl<'tcx> Term<'tcx> {
pub fn ty(&self) -> Ty<'tcx> {
if let Term::Ty(ty) = self { ty } else { panic!("Expected type") }
}
}
/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
/// 1. `T: TraitRef<..., Item = Type>`
/// - Or `T: TraitRef<..., Item = Const>`
/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
///
/// In particular, form #1 is "desugared" to the combination of a
@ -812,26 +836,7 @@ pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
#[derive(HashStable, TypeFoldable)]
pub struct ProjectionPredicate<'tcx> {
pub projection_ty: ProjectionTy<'tcx>,
pub ty: Ty<'tcx>,
}
/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
/// 1. `T: TraitRef<..., Item = Const>`
/// 2. `<T as TraitRef<...>>::Item == Const` (NYI)
///
/// In particular, form #1 is "desugared" to the combination of a
/// normal trait predicate (`T: TraitRef<...>`) and one of these
/// predicates. Form #2 is a broader form in that it also permits
/// equality between arbitrary types. Processing an instance of
/// Form #2 eventually yields one of these `ProjectionPredicate`
/// instances to normalize the LHS.
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
#[derive(HashStable, TypeFoldable)]
pub struct ConstPredicate<'tcx> {
pub projection: ProjectionTy<'tcx>,
pub c: &'tcx Const<'tcx>,
pub term: Term<'tcx>,
}
pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
@ -857,7 +862,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
}
pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> {
self.map_bound(|predicate| predicate.ty)
self.map_bound(|predicate| if let Term::Ty(ty) = predicate.term { ty } else { todo!() })
}
/// The `DefId` of the `TraitItem` for the associated type.

View File

@ -2499,7 +2499,14 @@ define_print_and_forward_display! {
}
ty::ProjectionPredicate<'tcx> {
p!(print(self.projection_ty), " == ", print(self.ty))
p!(print(self.projection_ty), " == ", print(self.term))
}
ty::Term<'tcx> {
match self {
ty::Term::Ty(ty) => p!(print(ty)),
ty::Term::Const(c) => p!(print(c)),
}
}
ty::ProjectionTy<'tcx> {

View File

@ -7,7 +7,7 @@
use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar};
use crate::ty::error::{ExpectedFound, TypeError};
use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, Term, Ty, TyCtxt, TypeFoldable};
use rustc_hir as ast;
use rustc_hir::def_id::DefId;
use rustc_span::DUMMY_SP;
@ -839,10 +839,13 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
a: ty::ProjectionPredicate<'tcx>,
b: ty::ProjectionPredicate<'tcx>,
) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> {
Ok(ty::ProjectionPredicate {
projection_ty: relation.relate(a.projection_ty, b.projection_ty)?,
ty: relation.relate(a.ty, b.ty)?,
})
match (a.term, b.term) {
(Term::Ty(a_ty), Term::Ty(b_ty)) => Ok(ty::ProjectionPredicate {
projection_ty: relation.relate(a.projection_ty, b.projection_ty)?,
term: relation.relate(a_ty, b_ty)?.into(),
}),
_ => todo!(),
}
}
}

View File

@ -6,7 +6,7 @@ use crate::mir::interpret;
use crate::mir::ProjectionKind;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{self, InferConst, Lift, Ty, TyCtxt};
use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt};
use rustc_data_structures::functor::IdFunctor;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::CRATE_DEF_INDEX;
@ -158,7 +158,7 @@ impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty)
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
}
}
@ -356,6 +356,16 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> {
}
}
impl<'a, 'tcx> Lift<'tcx> for Term<'a> {
type Lifted = ty::Term<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
Some(match self {
Term::Ty(ty) => Term::Ty(tcx.lift(ty)?),
Term::Const(c) => Term::Const(tcx.lift(c)?),
})
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
type Lifted = ty::TraitPredicate<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
@ -403,8 +413,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> {
impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> {
type Lifted = ty::ProjectionPredicate<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::ProjectionPredicate<'tcx>> {
tcx.lift((self.projection_ty, self.ty))
.map(|(projection_ty, ty)| ty::ProjectionPredicate { projection_ty, ty })
tcx.lift((self.projection_ty, self.term))
.map(|(projection_ty, term)| ty::ProjectionPredicate { projection_ty, term })
}
}

View File

@ -8,7 +8,7 @@ use crate::infer::canonical::Canonical;
use crate::ty::fold::ValidateBoundVars;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::InferTy::{self, *};
use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable};
use crate::ty::{self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeFoldable};
use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
use polonius_engine::Atom;
use rustc_data_structures::captures::Captures;
@ -1570,7 +1570,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
item_def_id: self.item_def_id,
substs: tcx.mk_substs_trait(self_ty, self.substs),
},
ty: self.ty,
term: self.ty.into(),
}
}
@ -1580,11 +1580,16 @@ impl<'tcx> ExistentialProjection<'tcx> {
) -> Self {
// Assert there is a Self.
projection_predicate.projection_ty.substs.type_at(0);
let ty = if let Term::Ty(ty) = projection_predicate.term {
ty
} else {
todo!();
};
Self {
item_def_id: projection_predicate.projection_ty.item_def_id,
substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
ty: projection_predicate.ty,
ty,
}
}
}

View File

@ -503,17 +503,15 @@ impl<'a> Parser<'a> {
) -> PResult<'a, AssocConstraintKind> {
let arg = self.parse_generic_arg(None)?;
let span = ident.span.to(self.prev_token.span);
let ty = match arg {
Some(GenericArg::Type(ty)) => ty,
Some(GenericArg::Const(c)) => {
return Ok(AssocConstraintKind::Equality { term: c.into() });
}
let term = match arg {
Some(GenericArg::Type(ty)) => ty.into(),
Some(GenericArg::Const(c)) => c.into(),
Some(GenericArg::Lifetime(lt)) => {
self.struct_span_err(span, "associated lifetimes are not supported")
.span_label(lt.ident.span, "the lifetime is given here")
.help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`")
.emit();
self.mk_ty(span, ast::TyKind::Err)
self.mk_ty(span, ast::TyKind::Err).into()
}
None => {
let after_eq = eq.shrink_to_hi();
@ -542,7 +540,7 @@ impl<'a> Parser<'a> {
return Err(err);
}
};
Ok(AssocConstraintKind::Equality { term: ty.into() })
Ok(AssocConstraintKind::Equality { term })
}
/// We do not permit arbitrary expressions as const arguments. They must be one of:

View File

@ -127,7 +127,8 @@ where
constness: _,
polarity: _,
}) => self.visit_trait(trait_ref),
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
let ty = term.ty();
ty.visit_with(self)?;
self.visit_projection_ty(projection_ty)
}
@ -1185,7 +1186,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
}
for (poly_predicate, _) in bounds.projection_bounds {
if self.visit(poly_predicate.skip_binder().ty).is_break()
if self.visit(poly_predicate.skip_binder().term.ty()).is_break()
|| self
.visit_projection_ty(poly_predicate.skip_binder().projection_ty)
.is_break()

View File

@ -1304,7 +1304,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
debug!(
"report_projection_error normalized_ty={:?} data.ty={:?}",
normalized_ty, data.ty
normalized_ty,
data.term.ty()
);
let is_normalized_ty_expected = !matches!(
@ -1318,12 +1319,12 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
is_normalized_ty_expected,
normalized_ty,
data.ty,
data.term.ty(),
) {
values = Some(infer::ValuePairs::Types(ExpectedFound::new(
is_normalized_ty_expected,
normalized_ty,
data.ty,
data.term.ty(),
)));
err_buf = error;
@ -1803,7 +1804,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
}
ty::PredicateKind::Projection(data) => {
let self_ty = data.projection_ty.self_ty();
let ty = data.ty;
let ty = data.term.ty();
if predicate.references_error() || self.is_tainted_by_errors() {
return;
}

View File

@ -214,7 +214,7 @@ fn project_and_unify_type<'cx, 'tcx>(
let infcx = selcx.infcx();
match infcx
.at(&obligation.cause, obligation.param_env)
.eq(normalized_ty, obligation.predicate.ty)
.eq(normalized_ty, obligation.predicate.term.ty())
{
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
@ -1615,7 +1615,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
substs: trait_ref.substs,
item_def_id: obligation.predicate.item_def_id,
},
ty,
term: ty.into(),
}
});
@ -1641,7 +1641,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
let predicate = ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy { substs, item_def_id: discriminant_def_id },
ty: self_ty.discriminant_ty(tcx),
term: self_ty.discriminant_ty(tcx).into(),
};
// We get here from `poly_project_and_unify_type` which replaces bound vars
@ -1674,7 +1674,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
let predicate = ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy { substs, item_def_id: metadata_def_id },
ty: metadata_ty,
term: metadata_ty.into(),
};
confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
@ -1747,7 +1747,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
substs: trait_ref.substs,
item_def_id: fn_once_output_def_id,
},
ty: ret_type,
term: ret_type.into(),
});
confirm_param_env_candidate(selcx, obligation, predicate, true)
@ -1803,7 +1803,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
Ok(InferOk { value: _, obligations }) => {
nested_obligations.extend(obligations);
assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
Progress { ty: cache_entry.ty, obligations: nested_obligations }
Progress { ty: cache_entry.term.ty(), obligations: nested_obligations }
}
Err(e) => {
let msg = format!(

View File

@ -62,7 +62,7 @@ pub(crate) fn update<'tcx, T>(
if let ty::PredicateKind::Projection(predicate) = obligation.predicate.kind().skip_binder() {
// If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
// we need to make it into one.
if let Some(vid) = predicate.ty.ty_vid() {
if let Some(vid) = predicate.term.ty().ty_vid() {
debug!("relationship: {:?}.output = true", vid);
engine.relationships().entry(vid).or_default().output = true;
}

View File

@ -116,7 +116,7 @@ pub fn predicate_obligations<'a, 'tcx>(
}
ty::PredicateKind::Projection(t) => {
wf.compute_projection(t.projection_ty);
wf.compute(t.ty.into());
wf.compute(t.term.ty().into());
}
ty::PredicateKind::WellFormed(arg) => {
wf.compute(arg);
@ -219,7 +219,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
// projection coming from another associated type. See
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
// `traits-assoc-type-in-supertrait-bad.rs`.
if let ty::Projection(projection_ty) = proj.ty.kind() {
if let ty::Projection(projection_ty) = proj.term.ty().kind() {
if let Some(&impl_item_id) =
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
{

View File

@ -227,7 +227,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq<RustInterner<'tcx>>>
{
fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq<RustInterner<'tcx>> {
chalk_ir::AliasEq {
ty: self.ty.lower_into(interner),
ty: self.term.ty().lower_into(interner),
alias: self.projection_ty.lower_into(interner),
}
}
@ -787,7 +787,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>
trait_bound: trait_ref.lower_into(interner),
associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
value: self.ty.lower_into(interner),
value: self.term.ty().lower_into(interner),
}
}
}

View File

@ -151,8 +151,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.bindings
.iter()
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
(true, hir::TypeBindingKind::Equality { ty }) => {
sess.source_map().span_to_snippet(ty.span).ok()
(true, hir::TypeBindingKind::Equality { term }) => {
let span = match term {
hir::Term::Ty(ty) => ty.span,
hir::Term::Const(c) => self.tcx().hir().span(c.hir_id),
};
sess.source_map().span_to_snippet(span).ok()
}
_ => None,
})

View File

@ -602,14 +602,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.iter()
.map(|binding| {
let kind = match binding.kind {
hir::TypeBindingKind::Equality { ty } => {
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
}
hir::TypeBindingKind::Const { ref c } => {
let local_did = self.tcx().hir().local_def_id(c.hir_id);
let c = Const::from_anon_const(self.tcx(), local_did);
ConvertedBindingKind::Const(&c)
}
hir::TypeBindingKind::Equality { ref term } => match term {
hir::Term::Ty(ref ty) => {
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
}
hir::Term::Const(ref c) => {
let local_did = self.tcx().hir().local_def_id(c.hir_id);
let c = Const::from_anon_const(self.tcx(), local_did);
ConvertedBindingKind::Const(&c)
}
},
hir::TypeBindingKind::Constraint { ref bounds } => {
ConvertedBindingKind::Constraint(bounds)
}
@ -1227,21 +1229,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
//
// `<T as Iterator>::Item = u32`
bounds.projection_bounds.push((
projection_ty.map_bound(|projection_ty| {
debug!(
"add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}",
projection_ty, projection_ty.substs
);
ty::ProjectionPredicate { projection_ty, ty }
projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
projection_ty,
term: ty.into(),
}),
binding.span,
));
}
ConvertedBindingKind::Const(c) => {
bounds.const_bounds.push((
projection_ty.map_bound(|projection_ty| ty::ConstPredicate {
projection: projection_ty,
c,
bounds.projection_bounds.push((
projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
projection_ty,
term: c.into(),
}),
binding.span,
));
@ -1393,7 +1392,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// A `Self` within the original bound will be substituted with a
// `trait_object_dummy_self`, so check for that.
let references_self =
pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
pred.skip_binder().term.ty().walk().any(|arg| arg == dummy_self.into());
// If the projection output contains `Self`, force the user to
// elaborate it explicitly to avoid a lot of complexity.

View File

@ -37,12 +37,6 @@ pub struct Bounds<'tcx> {
/// here.
pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
/// A list of const equality bounds. So if you had `T:
/// Iterator<N = 4>` this would include `<T as
/// Iterator>::N => 4`. Note that the self-type is explicit
/// here.
pub const_bounds: Vec<(ty::Binder<'tcx, ty::ConstPredicate<'tcx>>, Span)>,
/// `Some` if there is *no* `?Sized` predicate. The `span`
/// is the location in the source of the `T` declaration which can
/// be cited as the source of the `T: Sized` requirement.
@ -90,24 +84,7 @@ impl<'tcx> Bounds<'tcx> {
.projection_bounds
.iter()
.map(move |&(projection, span)| (projection.to_predicate(tcx), span));
let const_bounds = self.const_bounds.iter().map(move |&(bound, span)| {
// FIXME(...): what about the projection's generics?
// Is this the right local defid? Or should I get the self ty then
let pred = bound
.map_bound(|cp| {
let got =
ty::Const::from_anon_const(tcx, cp.projection.item_def_id.expect_local());
ty::PredicateKind::ConstEquate(cp.c, got)
})
.to_predicate(tcx);
(pred, span)
});
sized_predicate
.into_iter()
.chain(region_preds)
.chain(trait_bounds)
.chain(projection_bounds)
.chain(const_bounds)
sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds)
}
}

View File

@ -279,7 +279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
};
let ret_param_ty = projection.skip_binder().ty;
let ret_param_ty = projection.skip_binder().term.ty();
let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty);
debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
@ -706,7 +706,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Extract the type from the projection. Note that there can
// be no bound variables in this type because the "self type"
// does not have any regions in it.
let output_ty = self.resolve_vars_if_possible(predicate.ty);
let output_ty = self.resolve_vars_if_possible(predicate.term.ty());
debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
Some(output_ty)
}

View File

@ -1360,7 +1360,7 @@ pub fn check_type_bounds<'tcx>(
item_def_id: trait_ty.def_id,
substs: rebased_substs,
},
ty: impl_ty_value,
term: impl_ty_value.into(),
},
bound_vars,
)

View File

@ -789,7 +789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_def_id: projection_ty.item_def_id,
};
let ty = pred.skip_binder().ty;
let ty: Ty<'_> = pred.skip_binder().term.ty();
let obligation = format!("{} = {}", projection_ty, ty);
let quiet = format!("{} = {}", quiet_projection_ty, ty);

View File

@ -691,7 +691,11 @@ fn bounds_from_generic_predicates<'tcx>(
// insert the associated types where they correspond, but for now let's be "lazy" and
// propose this instead of the following valid resugaring:
// `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.item_def_id), p.ty));
where_clauses.push(format!(
"{} = {}",
tcx.def_path_str(p.projection_ty.item_def_id),
p.term.ty()
));
}
let where_clauses = if where_clauses.is_empty() {
String::new()

View File

@ -664,7 +664,11 @@ impl<'tcx> ItemCtxt<'tcx> {
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Type { .. } if param.hir_id == param_id => Some(&param.bounds),
GenericParamKind::Type { .. } | GenericParamKind::Const { .. }
if param.hir_id == param_id =>
{
Some(&param.bounds)
}
_ => None,
})
.flat_map(|bounds| bounds.iter())

View File

@ -67,11 +67,7 @@ fn opaque_type_bounds<'tcx>(
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
// Opaque types are implicitly sized unless a `?Sized` bound is found
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
let preds = bounds.predicates(tcx, item_ty);
let bounds = tcx.arena.alloc_from_iter(preds);
debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
bounds
tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
})
}

View File

@ -203,7 +203,7 @@ pub fn setup_constraining_predicates<'tcx>(
if !relies_only_on_inputs {
continue;
}
input_parameters.extend(parameters_for(&projection.ty, false));
input_parameters.extend(parameters_for(&projection.term, false));
} else {
continue;
}

View File

@ -199,7 +199,7 @@ fn unconstrained_parent_impl_substs<'tcx>(
for (predicate, _) in impl_generic_predicates.predicates.iter() {
if let ty::PredicateKind::Projection(proj) = predicate.kind().skip_binder() {
let projection_ty = proj.projection_ty;
let projected_ty = proj.ty;
let projected_ty = proj.term.ty();
let unbound_trait_ref = projection_ty.trait_ref(tcx);
if Some(unbound_trait_ref) == impl_trait_ref {

View File

@ -354,7 +354,8 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty:
impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
let ty::ProjectionPredicate { projection_ty, ty } = self;
let ty::ProjectionPredicate { projection_ty, term } = self;
let ty = term.ty();
WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) }
}
}
@ -623,8 +624,9 @@ fn clean_ty_generics(
.filter(|b| !b.is_sized_bound(cx)),
);
let proj = projection
.map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
let proj = projection.map(|p| {
(p.skip_binder().projection_ty.clean(cx), p.skip_binder().term.ty())
});
if let Some(((_, trait_did, name), rhs)) =
proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
{
@ -1566,7 +1568,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
.ident
.name,
kind: TypeBindingKind::Equality {
ty: proj.ty.clean(cx),
ty: proj.term.ty().clean(cx),
},
})
} else {
@ -2114,10 +2116,10 @@ impl Clean<TypeBinding> for hir::TypeBinding<'_> {
impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
match *self {
hir::TypeBindingKind::Equality { ref ty } => {
TypeBindingKind::Equality { ty: ty.clean(cx) }
}
hir::TypeBindingKind::Const { c: _ } => todo!(),
hir::TypeBindingKind::Equality { ref term } => match term {
hir::Term::Ty(ref ty) => TypeBindingKind::Equality { ty: ty.clean(cx) },
hir::Term::Const(ref _c) => todo!(),
},
hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint {
bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
},

@ -1 +1 @@
Subproject commit 2abffbf977a9e8c6ca4174a08fe5c4d7781f0aac
Subproject commit 6b3dbcc81a470e5da84576d63fcfc19e3b1154cd

View File

@ -10,5 +10,10 @@ impl Foo for Bar {
const N: usize = 3;
}
const TEST:usize = 3;
fn foo<F: Foo<N=3>>() {}
fn bar<F: Foo<N={TEST}>>() {}
fn main() {}

View File

@ -7,7 +7,7 @@ struct Bar;
const T: usize = 42;
impl Foo<N = 3> for Bar {
//~^ ERROR cannot constrain an associated constant to a value
//~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied
//~| ERROR associated type bindings are not allowed here
fn do_x(&self) -> [u8; 3] {
[0u8; 3]

View File

@ -1,11 +1,18 @@
error: cannot constrain an associated constant to a value
--> $DIR/issue-89013-no-kw.rs:9:10
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/issue-89013-no-kw.rs:9:6
|
LL | impl Foo<N = 3> for Bar {
| -^^^-
| | |
| | ...cannot be constrained to this value
| this associated constant...
| ^^^ expected 1 generic argument
|
note: trait defined here, with 1 generic parameter: `N`
--> $DIR/issue-89013-no-kw.rs:1:7
|
LL | trait Foo<const N: usize> {
| ^^^ -
help: add missing generic argument
|
LL | impl Foo<N, N = 3> for Bar {
| ++
error[E0229]: associated type bindings are not allowed here
--> $DIR/issue-89013-no-kw.rs:9:10
@ -15,4 +22,5 @@ LL | impl Foo<N = 3> for Bar {
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0229`.
Some errors have detailed explanations: E0107, E0229.
For more information about an error, try `rustc --explain E0107`.

View File

@ -8,7 +8,7 @@ const T: usize = 42;
impl Foo<N = const 3> for Bar {
//~^ ERROR expected lifetime, type, or constant, found keyword `const`
//~| ERROR cannot constrain an associated constant to a value
//~| ERROR this trait takes 1 generic
//~| ERROR associated type bindings are not allowed here
fn do_x(&self) -> [u8; 3] {
[0u8; 3]

View File

@ -10,14 +10,21 @@ LL - impl Foo<N = const 3> for Bar {
LL + impl Foo<N = 3> for Bar {
|
error: cannot constrain an associated constant to a value
--> $DIR/issue-89013.rs:9:10
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/issue-89013.rs:9:6
|
LL | impl Foo<N = const 3> for Bar {
| -^^^^^^^^^-
| | |
| | ...cannot be constrained to this value
| this associated constant...
| ^^^ expected 1 generic argument
|
note: trait defined here, with 1 generic parameter: `N`
--> $DIR/issue-89013.rs:1:7
|
LL | trait Foo<const N: usize> {
| ^^^ -
help: add missing generic argument
|
LL | impl Foo<N, N = const 3> for Bar {
| ++
error[E0229]: associated type bindings are not allowed here
--> $DIR/issue-89013.rs:9:10
@ -27,4 +34,5 @@ LL | impl Foo<N = const 3> for Bar {
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0229`.
Some errors have detailed explanations: E0107, E0229.
For more information about an error, try `rustc --explain E0107`.

View File

@ -1,7 +1,9 @@
// run-pass
#[cfg(FALSE)]
fn syntax() {
bar::<Item = 42>(); //~ ERROR cannot constrain an associated constant to a value
bar::<Item = { 42 }>(); //~ ERROR cannot constrain an associated constant to a value
bar::<Item = 42>();
bar::<Item = { 42 }>();
}
fn main() {}

View File

@ -1,20 +0,0 @@
error: cannot constrain an associated constant to a value
--> $DIR/recover-assoc-const-constraint.rs:3:11
|
LL | bar::<Item = 42>();
| ----^^^--
| | |
| | ...cannot be constrained to this value
| this associated constant...
error: cannot constrain an associated constant to a value
--> $DIR/recover-assoc-const-constraint.rs:4:11
|
LL | bar::<Item = { 42 }>();
| ----^^^------
| | |
| | ...cannot be constrained to this value
| this associated constant...
error: aborting due to 2 previous errors

@ -1 +1 @@
Subproject commit 06b9d31743210b788b130c8a484c2838afa6fc27
Subproject commit 358e79fe56fe374649275ca7aebaafd57ade0e8d

View File

@ -6,7 +6,7 @@ use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
Term, AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind,
};
use rustc_lint::{LateContext, LateLintPass};
@ -140,7 +140,7 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
if args.bindings.len() == 1;
let binding = &args.bindings[0];
if binding.ident.name == sym::Output;
if let TypeBindingKind::Equality{ty: output} = binding.kind;
if let TypeBindingKind::Equality{term: Term::Ty(output)} = binding.kind;
then {
return Some(output)
}

View File

@ -2143,10 +2143,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
// walk the associated type and check for Self
if let Some(self_adt) = self_ty.ty_adt_def() {
if contains_adt_constructor(projection_predicate.ty, self_adt) {
if contains_adt_constructor(projection_predicate.term.ty(), self_adt) {
return;
}
} else if contains_ty(projection_predicate.ty, self_ty) {
} else if contains_ty(projection_predicate.term.ty(), self_ty) {
return;
}
}

View File

@ -243,7 +243,7 @@ fn check_other_call_arg<'tcx>(
if if trait_predicate.def_id() == deref_trait_id {
if let [projection_predicate] = projection_predicates[..] {
let normalized_ty =
cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.ty);
cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term.ty());
implements_trait(cx, receiver_ty, deref_trait_id, &[])
&& get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty)
} else {

View File

@ -98,9 +98,9 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
if trait_pred.self_ty() == inp;
if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
then {
if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.ty) {
if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.term.ty()) {
args_to_check.push((i, "Ord".to_string()));
} else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.ty) {
} else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty()) {
args_to_check.push((i, "PartialOrd".to_string()));
}
}

@ -1 +1 @@
Subproject commit 0f8c96c92689af8378dbe9f466c6bf15a3a27458
Subproject commit 8e9ccbf97a70259b6c6576e8fd7d77d28238737e