Merge from rustc
This commit is contained in:
commit
7950562142
1369 changed files with 15150 additions and 10219 deletions
152
Cargo.lock
152
Cargo.lock
|
|
@ -284,6 +284,21 @@ dependencies = [
|
|||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_cmd"
|
||||
version = "2.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"bstr",
|
||||
"doc-comment",
|
||||
"predicates",
|
||||
"predicates-core",
|
||||
"predicates-tree",
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
|
|
@ -1095,6 +1110,12 @@ version = "0.1.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "difflib"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
|
|
@ -1197,6 +1218,12 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.12.0"
|
||||
|
|
@ -2337,6 +2364,33 @@ dependencies = [
|
|||
"topological-sort",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-trpl-listing"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"clap",
|
||||
"mdbook",
|
||||
"pulldown-cmark 0.10.3",
|
||||
"pulldown-cmark-to-cmark",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"toml 0.8.13",
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdbook-trpl-note"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"clap",
|
||||
"mdbook",
|
||||
"pulldown-cmark 0.10.3",
|
||||
"pulldown-cmark-to-cmark",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "measureme"
|
||||
version = "11.0.1"
|
||||
|
|
@ -2949,6 +3003,33 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"difflib",
|
||||
"predicates-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates-core"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
|
||||
|
||||
[[package]]
|
||||
name = "predicates-tree"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
|
||||
dependencies = [
|
||||
"predicates-core",
|
||||
"termtree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettydiff"
|
||||
version = "0.6.4"
|
||||
|
|
@ -3018,6 +3099,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"getopts",
|
||||
"memchr",
|
||||
"pulldown-cmark-escape",
|
||||
"unicase",
|
||||
|
|
@ -3029,6 +3111,15 @@ version = "0.10.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark-to-cmark"
|
||||
version = "13.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f609795c8d835f79dcfcf768415b9fb57ef1b74891e99f86e73f43a7a257163b"
|
||||
dependencies = [
|
||||
"pulldown-cmark 0.10.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "punycode"
|
||||
version = "0.4.1"
|
||||
|
|
@ -3276,6 +3367,8 @@ dependencies = [
|
|||
"clap",
|
||||
"env_logger",
|
||||
"mdbook",
|
||||
"mdbook-trpl-listing",
|
||||
"mdbook-trpl-note",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5386,6 +5479,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termtree"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.0"
|
||||
|
|
@ -5558,7 +5657,19 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
"toml_edit 0.19.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.22.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5580,7 +5691,20 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
"winnow 0.5.40",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow 0.6.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5990,6 +6114,15 @@ version = "0.9.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
|
|
@ -6302,6 +6435,15 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.5.4"
|
||||
|
|
@ -6319,6 +6461,12 @@ dependencies = [
|
|||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
|
||||
|
||||
[[package]]
|
||||
name = "xz2"
|
||||
version = "0.1.7"
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ impl PathSegment {
|
|||
}
|
||||
}
|
||||
|
||||
/// The arguments of a path segment.
|
||||
/// The generic arguments and associated item constraints of a path segment.
|
||||
///
|
||||
/// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
|
|
@ -221,14 +221,13 @@ pub struct AngleBracketedArgs {
|
|||
pub args: ThinVec<AngleBracketedArg>,
|
||||
}
|
||||
|
||||
/// Either an argument for a parameter e.g., `'a`, `Vec<u8>`, `0`,
|
||||
/// or a constraint on an associated item, e.g., `Item = String` or `Item: Bound`.
|
||||
/// Either an argument for a generic parameter or a constraint on an associated item.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum AngleBracketedArg {
|
||||
/// Argument for a generic parameter.
|
||||
/// A generic argument for a generic parameter.
|
||||
Arg(GenericArg),
|
||||
/// Constraint for an associated item.
|
||||
Constraint(AssocConstraint),
|
||||
/// A constraint on an associated item.
|
||||
Constraint(AssocItemConstraint),
|
||||
}
|
||||
|
||||
impl AngleBracketedArg {
|
||||
|
|
@ -418,7 +417,7 @@ impl Default for WhereClause {
|
|||
/// A single predicate in a where-clause.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum WherePredicate {
|
||||
/// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
|
||||
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
|
||||
BoundPredicate(WhereBoundPredicate),
|
||||
/// A lifetime predicate (e.g., `'a: 'b + 'c`).
|
||||
RegionPredicate(WhereRegionPredicate),
|
||||
|
|
@ -2034,18 +2033,25 @@ impl UintTy {
|
|||
}
|
||||
}
|
||||
|
||||
/// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
|
||||
/// `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`).
|
||||
/// A constraint on an associated item.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// * the `A = Ty` and `B = Ty` in `Trait<A = Ty, B = Ty>`
|
||||
/// * the `G<Ty> = Ty` in `Trait<G<Ty> = Ty>`
|
||||
/// * the `A: Bound` in `Trait<A: Bound>`
|
||||
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
|
||||
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
|
||||
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct AssocConstraint {
|
||||
pub struct AssocItemConstraint {
|
||||
pub id: NodeId,
|
||||
pub ident: Ident,
|
||||
pub gen_args: Option<GenericArgs>,
|
||||
pub kind: AssocConstraintKind,
|
||||
pub kind: AssocItemConstraintKind,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// The kinds of an `AssocConstraint`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum Term {
|
||||
Ty(P<Ty>),
|
||||
|
|
@ -2064,12 +2070,17 @@ impl From<AnonConst> for Term {
|
|||
}
|
||||
}
|
||||
|
||||
/// The kinds of an `AssocConstraint`.
|
||||
/// The kind of [associated item constraint][AssocItemConstraint].
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum AssocConstraintKind {
|
||||
/// E.g., `A = Bar`, `A = 3` in `Foo<A = Bar>` where A is an associated type.
|
||||
pub enum AssocItemConstraintKind {
|
||||
/// An equality constraint for an associated item (e.g., `AssocTy = Ty` in `Trait<AssocTy = Ty>`).
|
||||
///
|
||||
/// Also known as an *associated item binding* (we *bind* an associated item to a term).
|
||||
///
|
||||
/// Furthermore, associated type equality constraints can also be referred to as *associated type
|
||||
/// bindings*. Similarly with associated const equality constraints and *associated const bindings*.
|
||||
Equality { term: Term },
|
||||
/// E.g. `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`.
|
||||
/// A bound on an associated type (e.g., `AssocTy: Bound` in `Trait<AssocTy: Bound>`).
|
||||
Bound { bounds: GenericBounds },
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@ pub trait MutVisitor: Sized {
|
|||
noop_visit_lifetime(l, self);
|
||||
}
|
||||
|
||||
fn visit_constraint(&mut self, t: &mut AssocConstraint) {
|
||||
noop_visit_constraint(t, self);
|
||||
fn visit_assoc_item_constraint(&mut self, c: &mut AssocItemConstraint) {
|
||||
noop_visit_assoc_item_constraint(c, self);
|
||||
}
|
||||
|
||||
fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) {
|
||||
|
|
@ -463,8 +463,8 @@ pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[
|
|||
smallvec![arm]
|
||||
}
|
||||
|
||||
fn noop_visit_constraint<T: MutVisitor>(
|
||||
AssocConstraint { id, ident, gen_args, kind, span }: &mut AssocConstraint,
|
||||
fn noop_visit_assoc_item_constraint<T: MutVisitor>(
|
||||
AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint,
|
||||
vis: &mut T,
|
||||
) {
|
||||
vis.visit_id(id);
|
||||
|
|
@ -473,11 +473,11 @@ fn noop_visit_constraint<T: MutVisitor>(
|
|||
vis.visit_generic_args(gen_args);
|
||||
}
|
||||
match kind {
|
||||
AssocConstraintKind::Equality { term } => match term {
|
||||
AssocItemConstraintKind::Equality { term } => match term {
|
||||
Term::Ty(ty) => vis.visit_ty(ty),
|
||||
Term::Const(c) => vis.visit_anon_const(c),
|
||||
},
|
||||
AssocConstraintKind::Bound { bounds } => visit_bounds(bounds, vis),
|
||||
AssocItemConstraintKind::Bound { bounds } => visit_bounds(bounds, vis),
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
|
@ -607,7 +607,7 @@ fn noop_visit_angle_bracketed_parameter_data<T: MutVisitor>(
|
|||
let AngleBracketedArgs { args, span } = data;
|
||||
visit_thin_vec(args, |arg| match arg {
|
||||
AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg),
|
||||
AngleBracketedArg::Constraint(constraint) => vis.visit_constraint(constraint),
|
||||
AngleBracketedArg::Constraint(constraint) => vis.visit_assoc_item_constraint(constraint),
|
||||
});
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -246,8 +246,11 @@ pub trait Visitor<'ast>: Sized {
|
|||
fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result {
|
||||
walk_generic_arg(self, generic_arg)
|
||||
}
|
||||
fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) -> Self::Result {
|
||||
walk_assoc_constraint(self, constraint)
|
||||
fn visit_assoc_item_constraint(
|
||||
&mut self,
|
||||
constraint: &'ast AssocItemConstraint,
|
||||
) -> Self::Result {
|
||||
walk_assoc_item_constraint(self, constraint)
|
||||
}
|
||||
fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result {
|
||||
walk_attribute(self, attr)
|
||||
|
|
@ -558,7 +561,7 @@ where
|
|||
match arg {
|
||||
AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)),
|
||||
AngleBracketedArg::Constraint(c) => {
|
||||
try_visit!(visitor.visit_assoc_constraint(c))
|
||||
try_visit!(visitor.visit_assoc_item_constraint(c))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -582,18 +585,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(
|
||||
pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
constraint: &'a AssocConstraint,
|
||||
constraint: &'a AssocItemConstraint,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_ident(constraint.ident));
|
||||
visit_opt!(visitor, visit_generic_args, &constraint.gen_args);
|
||||
match &constraint.kind {
|
||||
AssocConstraintKind::Equality { term } => match term {
|
||||
AssocItemConstraintKind::Equality { term } => match term {
|
||||
Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)),
|
||||
Term::Const(c) => try_visit!(visitor.visit_anon_const(c)),
|
||||
},
|
||||
AssocConstraintKind::Bound { bounds } => {
|
||||
AssocItemConstraintKind::Bound { bounds } => {
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
StmtKind::Empty => {}
|
||||
StmtKind::MacCall(..) => panic!("shouldn't exist here"),
|
||||
}
|
||||
ast_stmts = &ast_stmts[1..];
|
||||
ast_stmts = tail;
|
||||
}
|
||||
(self.arena.alloc_from_iter(stmts), expr)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,10 +325,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_assoc_type_binding(&mut self, type_binding: &'hir TypeBinding<'hir>) {
|
||||
self.insert(type_binding.span, type_binding.hir_id, Node::TypeBinding(type_binding));
|
||||
self.with_parent(type_binding.hir_id, |this| {
|
||||
intravisit::walk_assoc_type_binding(this, type_binding)
|
||||
fn visit_assoc_item_constraint(&mut self, constraint: &'hir AssocItemConstraint<'hir>) {
|
||||
self.insert(constraint.span, constraint.hir_id, Node::AssocItemConstraint(constraint));
|
||||
self.with_parent(constraint.hir_id, |this| {
|
||||
intravisit::walk_assoc_item_constraint(this, constraint)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -967,24 +967,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.flattened() }
|
||||
}
|
||||
|
||||
/// Given an associated type constraint like one of these:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// T: Iterator<Item: Debug>
|
||||
/// ^^^^^^^^^^^
|
||||
/// T: Iterator<Item = Debug>
|
||||
/// ^^^^^^^^^^^^
|
||||
/// ```
|
||||
///
|
||||
/// returns a `hir::TypeBinding` representing `Item`.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_assoc_ty_constraint(
|
||||
/// Lower an associated item constraint.
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn lower_assoc_item_constraint(
|
||||
&mut self,
|
||||
constraint: &AssocConstraint,
|
||||
constraint: &AssocItemConstraint,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::TypeBinding<'hir> {
|
||||
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
|
||||
// lower generic arguments of identifier in constraint
|
||||
) -> hir::AssocItemConstraint<'hir> {
|
||||
debug!(?constraint, ?itctx);
|
||||
// Lower the generic arguments for the associated item.
|
||||
let gen_args = if let Some(gen_args) = &constraint.gen_args {
|
||||
let gen_args_ctor = match gen_args {
|
||||
GenericArgs::AngleBracketed(data) => {
|
||||
|
|
@ -1000,7 +991,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
bindings: &[],
|
||||
constraints: &[],
|
||||
parenthesized,
|
||||
span: data.inputs_span,
|
||||
}
|
||||
|
|
@ -1030,7 +1021,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
err.emit();
|
||||
GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
bindings: &[],
|
||||
constraints: &[],
|
||||
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
|
||||
span: data.span,
|
||||
}
|
||||
|
|
@ -1052,14 +1043,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.arena.alloc(hir::GenericArgs::none())
|
||||
};
|
||||
let kind = match &constraint.kind {
|
||||
AssocConstraintKind::Equality { term } => {
|
||||
AssocItemConstraintKind::Equality { term } => {
|
||||
let term = match term {
|
||||
Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
|
||||
Term::Const(c) => self.lower_anon_const(c).into(),
|
||||
};
|
||||
hir::TypeBindingKind::Equality { term }
|
||||
hir::AssocItemConstraintKind::Equality { term }
|
||||
}
|
||||
AssocConstraintKind::Bound { bounds } => {
|
||||
AssocItemConstraintKind::Bound { bounds } => {
|
||||
// Disallow ATB in dyn types
|
||||
if self.is_in_dyn_type {
|
||||
let suggestion = match itctx {
|
||||
|
|
@ -1083,18 +1074,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
});
|
||||
let err_ty =
|
||||
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
|
||||
hir::TypeBindingKind::Equality { term: err_ty.into() }
|
||||
hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
|
||||
} else {
|
||||
// Desugar `AssocTy: Bounds` into a type binding where the
|
||||
// Desugar `AssocTy: Bounds` into an assoc type binding where the
|
||||
// later desugars into a trait predicate.
|
||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||
|
||||
hir::TypeBindingKind::Constraint { bounds }
|
||||
hir::AssocItemConstraintKind::Bound { bounds }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
hir::TypeBinding {
|
||||
hir::AssocItemConstraint {
|
||||
hir_id: self.lower_node_id(constraint.id),
|
||||
ident: self.lower_ident(constraint.ident),
|
||||
gen_args,
|
||||
|
|
@ -2014,7 +2005,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
let bound_args = self.arena.alloc(hir::GenericArgs {
|
||||
args: &[],
|
||||
bindings: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, opaque_ty_span, output_ty)],
|
||||
constraints: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, opaque_ty_span, output_ty)],
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span_ext: DUMMY_SP,
|
||||
});
|
||||
|
|
@ -2587,10 +2578,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper struct for delayed construction of GenericArgs.
|
||||
/// Helper struct for the delayed construction of [`hir::GenericArgs`].
|
||||
struct GenericArgsCtor<'hir> {
|
||||
args: SmallVec<[hir::GenericArg<'hir>; 4]>,
|
||||
bindings: &'hir [hir::TypeBinding<'hir>],
|
||||
constraints: &'hir [hir::AssocItemConstraint<'hir>],
|
||||
parenthesized: hir::GenericArgsParentheses,
|
||||
span: Span,
|
||||
}
|
||||
|
|
@ -2670,14 +2661,14 @@ impl<'hir> GenericArgsCtor<'hir> {
|
|||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.args.is_empty()
|
||||
&& self.bindings.is_empty()
|
||||
&& self.constraints.is_empty()
|
||||
&& self.parenthesized == hir::GenericArgsParentheses::No
|
||||
}
|
||||
|
||||
fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> {
|
||||
let ga = hir::GenericArgs {
|
||||
args: this.arena.alloc_from_iter(self.args),
|
||||
bindings: self.bindings,
|
||||
constraints: self.constraints,
|
||||
parenthesized: self.parenthesized,
|
||||
span_ext: this.lower_span(self.span),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
(
|
||||
GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
bindings: &[],
|
||||
constraints: &[],
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span: path_span.shrink_to_hi(),
|
||||
},
|
||||
|
|
@ -390,13 +390,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
AngleBracketedArg::Constraint(_) => None,
|
||||
})
|
||||
.collect();
|
||||
let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
|
||||
AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)),
|
||||
AngleBracketedArg::Arg(_) => None,
|
||||
}));
|
||||
let constraints =
|
||||
self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
|
||||
AngleBracketedArg::Constraint(c) => {
|
||||
Some(self.lower_assoc_item_constraint(c, itctx))
|
||||
}
|
||||
AngleBracketedArg::Arg(_) => None,
|
||||
}));
|
||||
let ctor = GenericArgsCtor {
|
||||
args,
|
||||
bindings,
|
||||
constraints,
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span: data.span,
|
||||
};
|
||||
|
|
@ -454,12 +457,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
Some(bound_modifier_allowed_features),
|
||||
);
|
||||
}
|
||||
let binding = self.assoc_ty_binding(sym::Output, output_span, output_ty);
|
||||
let constraint = self.assoc_ty_binding(sym::Output, output_span, output_ty);
|
||||
|
||||
(
|
||||
GenericArgsCtor {
|
||||
args,
|
||||
bindings: arena_vec![self; binding],
|
||||
constraints: arena_vec![self; constraint],
|
||||
parenthesized: hir::GenericArgsParentheses::ParenSugar,
|
||||
span: data.inputs_span,
|
||||
},
|
||||
|
|
@ -467,24 +470,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
)
|
||||
}
|
||||
|
||||
/// An associated type binding `$assoc_ty_name = $ty`.
|
||||
/// An associated type binding (i.e., associated type equality constraint).
|
||||
pub(crate) fn assoc_ty_binding(
|
||||
&mut self,
|
||||
assoc_ty_name: rustc_span::Symbol,
|
||||
span: Span,
|
||||
ty: &'hir hir::Ty<'hir>,
|
||||
) -> hir::TypeBinding<'hir> {
|
||||
) -> hir::AssocItemConstraint<'hir> {
|
||||
let ident = Ident::with_dummy_span(assoc_ty_name);
|
||||
let kind = hir::TypeBindingKind::Equality { term: ty.into() };
|
||||
let kind = hir::AssocItemConstraintKind::Equality { term: ty.into() };
|
||||
let args = arena_vec![self;];
|
||||
let bindings = arena_vec![self;];
|
||||
let constraints = arena_vec![self;];
|
||||
let gen_args = self.arena.alloc(hir::GenericArgs {
|
||||
args,
|
||||
bindings,
|
||||
constraints,
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span_ext: DUMMY_SP,
|
||||
});
|
||||
hir::TypeBinding {
|
||||
hir::AssocItemConstraint {
|
||||
hir_id: self.next_id(),
|
||||
gen_args,
|
||||
span: self.lower_span(span),
|
||||
|
|
|
|||
|
|
@ -671,7 +671,7 @@ impl<'a> AstValidator<'a> {
|
|||
let constraint_sugg = data.args.iter().filter_map(|a| match a {
|
||||
AngleBracketedArg::Arg(_) => None,
|
||||
AngleBracketedArg::Constraint(c) => {
|
||||
Some(pprust::to_string(|s| s.print_assoc_constraint(c)))
|
||||
Some(pprust::to_string(|s| s.print_assoc_item_constraint(c)))
|
||||
}
|
||||
});
|
||||
format!(
|
||||
|
|
@ -1199,11 +1199,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
for arg in &data.args {
|
||||
match arg {
|
||||
AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
|
||||
// Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
|
||||
// are allowed to contain nested `impl Trait`.
|
||||
// Associated type bindings such as `Item = impl Debug` in
|
||||
// `Iterator<Item = Debug>` are allowed to contain nested `impl Trait`.
|
||||
AngleBracketedArg::Constraint(constraint) => {
|
||||
self.with_impl_trait(None, |this| {
|
||||
this.visit_assoc_constraint(constraint);
|
||||
this.visit_assoc_item_constraint(constraint);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1363,7 +1363,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
// The lowered form of parenthesized generic args contains a type binding.
|
||||
// The lowered form of parenthesized generic args contains an associated type binding.
|
||||
Some(ast::GenericArgs::Parenthesized(args)) => {
|
||||
self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation {
|
||||
span: args.span,
|
||||
|
|
@ -1589,11 +1589,13 @@ fn deny_equality_constraints(
|
|||
let len = assoc_path.segments.len() - 1;
|
||||
let gen_args = args.as_deref().cloned();
|
||||
// Build `<Bar = RhsTy>`.
|
||||
let arg = AngleBracketedArg::Constraint(AssocConstraint {
|
||||
let arg = AngleBracketedArg::Constraint(AssocItemConstraint {
|
||||
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
||||
ident: *ident,
|
||||
gen_args,
|
||||
kind: AssocConstraintKind::Equality { term: predicate.rhs_ty.clone().into() },
|
||||
kind: AssocItemConstraintKind::Equality {
|
||||
term: predicate.rhs_ty.clone().into(),
|
||||
},
|
||||
span: ident.span,
|
||||
});
|
||||
// Add `<Bar = RhsTy>` to `Foo`.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId};
|
||||
use rustc_ast::{attr, AssocItemConstraint, AssocItemConstraintKind, NodeId};
|
||||
use rustc_ast::{token, PatKind};
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
|
||||
|
|
@ -344,7 +344,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
for predicate in &g.where_clause.predicates {
|
||||
match predicate {
|
||||
ast::WherePredicate::BoundPredicate(bound_pred) => {
|
||||
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
|
||||
// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
|
||||
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -445,21 +445,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
visit::walk_fn(self, fn_kind)
|
||||
}
|
||||
|
||||
fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) {
|
||||
if let AssocConstraintKind::Bound { .. } = constraint.kind {
|
||||
if let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref()
|
||||
&& args.inputs.is_empty()
|
||||
&& matches!(args.output, ast::FnRetTy::Default(..))
|
||||
{
|
||||
gate!(
|
||||
&self,
|
||||
return_type_notation,
|
||||
constraint.span,
|
||||
"return type notation is experimental"
|
||||
);
|
||||
}
|
||||
fn visit_assoc_item_constraint(&mut self, constraint: &'a AssocItemConstraint) {
|
||||
if let AssocItemConstraintKind::Bound { .. } = constraint.kind
|
||||
&& let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref()
|
||||
&& args.inputs.is_empty()
|
||||
&& let ast::FnRetTy::Default(..) = args.output
|
||||
{
|
||||
gate!(
|
||||
&self,
|
||||
return_type_notation,
|
||||
constraint.span,
|
||||
"return type notation is experimental"
|
||||
);
|
||||
}
|
||||
visit::walk_assoc_constraint(self, constraint)
|
||||
|
||||
visit::walk_assoc_item_constraint(self, constraint)
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
|
|
|
|||
|
|
@ -119,9 +119,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
|
|||
self.count += 1;
|
||||
walk_generic_args(self, generic_args)
|
||||
}
|
||||
fn visit_assoc_constraint(&mut self, constraint: &AssocConstraint) {
|
||||
fn visit_assoc_item_constraint(&mut self, constraint: &AssocItemConstraint) {
|
||||
self.count += 1;
|
||||
walk_assoc_constraint(self, constraint)
|
||||
walk_assoc_item_constraint(self, constraint)
|
||||
}
|
||||
fn visit_attribute(&mut self, _attr: &Attribute) {
|
||||
self.count += 1;
|
||||
|
|
|
|||
|
|
@ -1045,7 +1045,7 @@ impl<'a> PrintState<'a> for State<'a> {
|
|||
self.word("<");
|
||||
self.commasep(Inconsistent, &data.args, |s, arg| match arg {
|
||||
ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a),
|
||||
ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c),
|
||||
ast::AngleBracketedArg::Constraint(c) => s.print_assoc_item_constraint(c),
|
||||
});
|
||||
self.word(">")
|
||||
}
|
||||
|
|
@ -1097,21 +1097,21 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) {
|
||||
pub fn print_assoc_item_constraint(&mut self, constraint: &ast::AssocItemConstraint) {
|
||||
self.print_ident(constraint.ident);
|
||||
if let Some(args) = constraint.gen_args.as_ref() {
|
||||
self.print_generic_args(args, false)
|
||||
}
|
||||
self.space();
|
||||
match &constraint.kind {
|
||||
ast::AssocConstraintKind::Equality { term } => {
|
||||
ast::AssocItemConstraintKind::Equality { term } => {
|
||||
self.word_space("=");
|
||||
match term {
|
||||
Term::Ty(ty) => self.print_type(ty),
|
||||
Term::Const(c) => self.print_expr_anon_const(c, &[]),
|
||||
}
|
||||
}
|
||||
ast::AssocConstraintKind::Bound { bounds } => {
|
||||
ast::AssocItemConstraintKind::Bound { bounds } => {
|
||||
if !bounds.is_empty() {
|
||||
self.word_nbsp(":");
|
||||
self.print_type_bounds(bounds);
|
||||
|
|
|
|||
|
|
@ -399,8 +399,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
let hir = self.infcx.tcx.hir();
|
||||
if let Some(body_id) = hir.maybe_body_owned_by(self.mir_def_id()) {
|
||||
let expr = hir.body(body_id).value;
|
||||
if let Some(body) = hir.maybe_body_owned_by(self.mir_def_id()) {
|
||||
let expr = body.value;
|
||||
let place = &self.move_data.move_paths[mpi].place;
|
||||
let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span);
|
||||
let mut finder = ExpressionFinder {
|
||||
|
|
@ -556,11 +556,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// We use the statements were the binding was initialized, and inspect the HIR to look
|
||||
// for the branching codepaths that aren't covered, to point at them.
|
||||
let map = self.infcx.tcx.hir();
|
||||
let body_id = map.body_owned_by(self.mir_def_id());
|
||||
let body = map.body(body_id);
|
||||
let body = map.body_owned_by(self.mir_def_id());
|
||||
|
||||
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
|
||||
visitor.visit_body(body);
|
||||
visitor.visit_body(&body);
|
||||
|
||||
let mut show_assign_sugg = false;
|
||||
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
|
||||
|
|
@ -665,7 +664,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
let mut visitor = LetVisitor { decl_span, sugg_span: None };
|
||||
visitor.visit_body(body);
|
||||
visitor.visit_body(&body);
|
||||
if let Some(span) = visitor.sugg_span {
|
||||
self.suggest_assign_value(&mut err, moved_place, span);
|
||||
}
|
||||
|
|
@ -1348,7 +1347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
return;
|
||||
};
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let ocx = ObligationCtxt::new(self.infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
|
||||
let cause = ObligationCause::misc(span, self.mir_def_id());
|
||||
|
||||
ocx.register_bound(cause, self.param_env, ty, def_id);
|
||||
|
|
@ -1362,7 +1361,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
match *predicate.self_ty().kind() {
|
||||
ty::Param(param_ty) => Ok((
|
||||
generics.type_param(param_ty, tcx),
|
||||
predicate.trait_ref.print_only_trait_path().to_string(),
|
||||
predicate.trait_ref.print_trait_sugared().to_string(),
|
||||
)),
|
||||
_ => Err(()),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_hir::def::{CtorKind, Namespace};
|
|||
use rustc_hir::CoroutineKind;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::BoundRegionConversionTime;
|
||||
use rustc_infer::traits::{FulfillmentErrorCode, SelectionError};
|
||||
use rustc_infer::traits::SelectionError;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
|
|
@ -29,7 +29,9 @@ use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
|||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
|
||||
use rustc_trait_selection::traits::{
|
||||
type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,
|
||||
};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use hir::{ExprKind, Param};
|
|||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, Node};
|
||||
use rustc_infer::traits;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, Upcast};
|
||||
|
|
@ -18,6 +17,7 @@ use rustc_span::symbol::{kw, Symbol};
|
|||
use rustc_span::{sym, BytePos, DesugaringKind, Span};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||
|
||||
use crate::diagnostics::BorrowedContentSource;
|
||||
|
|
@ -647,8 +647,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let hir_map = self.infcx.tcx.hir();
|
||||
let def_id = self.body.source.def_id();
|
||||
let Some(local_def_id) = def_id.as_local() else { return };
|
||||
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return };
|
||||
let body = self.infcx.tcx.hir().body(body_id);
|
||||
let Some(body) = hir_map.maybe_body_owned_by(local_def_id) else { return };
|
||||
|
||||
let mut v = SuggestIndexOperatorAlternativeVisitor {
|
||||
assign_span: span,
|
||||
|
|
@ -656,7 +655,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
ty,
|
||||
suggested: false,
|
||||
};
|
||||
v.visit_body(body);
|
||||
v.visit_body(&body);
|
||||
if !v.suggested {
|
||||
err.help(format!(
|
||||
"to modify a `{ty}`, use `.get_mut()`, `.insert()` or the entry API",
|
||||
|
|
@ -746,9 +745,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
// `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)`
|
||||
let def_id = self.body.source.def_id();
|
||||
if let Some(local_def_id) = def_id.as_local()
|
||||
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
|
||||
&& let body = self.infcx.tcx.hir().body(body_id)
|
||||
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(body).break_value()
|
||||
&& let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
|
||||
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value()
|
||||
&& let node = self.infcx.tcx.hir_node(hir_id)
|
||||
&& let hir::Node::LetStmt(hir::LetStmt {
|
||||
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
|
||||
|
|
@ -867,8 +865,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id())
|
||||
&& let Block(block, _) = hir_map.body(body_id).value.kind
|
||||
if let Some(body) = hir_map.maybe_body_owned_by(self.mir_def_id())
|
||||
&& let Block(block, _) = body.value.kind
|
||||
{
|
||||
// `span` corresponds to the expression being iterated, find the `for`-loop desugared
|
||||
// expression with that span in order to identify potential fixes when encountering a
|
||||
|
|
@ -1189,10 +1187,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
Some((false, err_label_span, message, _)) => {
|
||||
let def_id = self.body.source.def_id();
|
||||
let hir_id = if let Some(local_def_id) = def_id.as_local()
|
||||
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
|
||||
&& let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
|
||||
{
|
||||
let body = self.infcx.tcx.hir().body(body_id);
|
||||
BindingFinder { span: err_label_span }.visit_body(body).break_value()
|
||||
BindingFinder { span: err_label_span }.visit_body(&body).break_value()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1183,8 +1183,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) {
|
||||
let map = self.infcx.tcx.hir();
|
||||
let body_id = map.body_owned_by(self.mir_def_id());
|
||||
let expr = &map.body(body_id).value.peel_blocks();
|
||||
let body = map.body_owned_by(self.mir_def_id());
|
||||
let expr = &body.value.peel_blocks();
|
||||
let mut closure_span = None::<rustc_span::Span>;
|
||||
match expr.kind {
|
||||
hir::ExprKind::MethodCall(.., args, _) => {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_middle::ty::print::RegionHighlightMode;
|
|||
use rustc_middle::ty::{self, RegionVid, Ty};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
|
||||
|
|
@ -843,13 +843,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
}) = opaque_ty.kind
|
||||
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
|
||||
&& let Some(args) = segment.args
|
||||
&& let [
|
||||
hir::TypeBinding {
|
||||
ident: Ident { name: sym::Output, .. },
|
||||
kind: hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) },
|
||||
..
|
||||
},
|
||||
] = args.bindings
|
||||
&& let [constraint] = args.constraints
|
||||
&& constraint.ident.name == sym::Output
|
||||
&& let Some(ty) = constraint.ty()
|
||||
{
|
||||
ty
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -125,8 +125,8 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
placeholder_indices,
|
||||
placeholder_index_to_region: _,
|
||||
liveness_constraints,
|
||||
outlives_constraints,
|
||||
member_constraints,
|
||||
mut outlives_constraints,
|
||||
mut member_constraints,
|
||||
universe_causes,
|
||||
type_tests,
|
||||
} = constraints;
|
||||
|
|
@ -144,6 +144,16 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||
&universal_region_relations,
|
||||
);
|
||||
|
||||
if let Some(guar) = universal_regions.tainted_by_errors() {
|
||||
// Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
|
||||
// outlives bounds that we may end up checking.
|
||||
outlives_constraints = Default::default();
|
||||
member_constraints = Default::default();
|
||||
|
||||
// Also taint the entire scope.
|
||||
infcx.set_tainted_by_errors(guar);
|
||||
}
|
||||
|
||||
let mut regioncx = RegionInferenceContext::new(
|
||||
infcx,
|
||||
var_origins,
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ fn check_opaque_type_well_formed<'tcx>(
|
|||
.with_next_trait_solver(next_trait_solver)
|
||||
.with_opaque_type_inference(parent_def_id)
|
||||
.build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
let identity_args = GenericArgs::identity_for_item(tcx, def_id);
|
||||
|
||||
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ use rustc_middle::traits::query::NoSolution;
|
|||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::solve::deeply_normalize;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
use rustc_trait_selection::traits::ScrubbedTraitError;
|
||||
|
||||
use crate::{
|
||||
constraints::OutlivesConstraint,
|
||||
|
|
@ -282,11 +282,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
) -> Ty<'tcx> {
|
||||
let result = CustomTypeOp::new(
|
||||
|ocx| {
|
||||
deeply_normalize(
|
||||
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
|
||||
ocx.deeply_normalize(
|
||||
&ObligationCause::dummy_with_span(self.span),
|
||||
self.param_env,
|
||||
ty,
|
||||
)
|
||||
.map_err(|_| NoSolution)
|
||||
.map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
|
||||
},
|
||||
"normalize type outlives obligation",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ use std::rc::Rc;
|
|||
use crate::{
|
||||
constraints::OutlivesConstraintSet,
|
||||
facts::{AllFacts, AllFactsExt},
|
||||
location::LocationTable,
|
||||
region_infer::values::LivenessValues,
|
||||
universal_regions::UniversalRegions,
|
||||
};
|
||||
|
|
@ -39,7 +38,6 @@ pub(super) fn generate<'mir, 'tcx>(
|
|||
elements: &Rc<DenseLocationMap>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
use_polonius: bool,
|
||||
) {
|
||||
debug!("liveness::generate");
|
||||
|
|
@ -53,11 +51,9 @@ pub(super) fn generate<'mir, 'tcx>(
|
|||
compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
|
||||
let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
|
||||
|
||||
let polonius_drop_used = facts_enabled.then(|| {
|
||||
let mut drop_used = Vec::new();
|
||||
polonius::populate_access_facts(typeck, body, location_table, move_data, &mut drop_used);
|
||||
drop_used
|
||||
});
|
||||
if facts_enabled {
|
||||
polonius::populate_access_facts(typeck, body, move_data);
|
||||
};
|
||||
|
||||
trace::trace(
|
||||
typeck,
|
||||
|
|
@ -67,7 +63,6 @@ pub(super) fn generate<'mir, 'tcx>(
|
|||
move_data,
|
||||
relevant_live_locals,
|
||||
boring_locals,
|
||||
polonius_drop_used,
|
||||
);
|
||||
|
||||
// Mark regions that should be live where they appear within rvalues or within a call: like
|
||||
|
|
|
|||
|
|
@ -85,13 +85,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> {
|
|||
pub(super) fn populate_access_facts<'a, 'tcx>(
|
||||
typeck: &mut TypeChecker<'a, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
move_data: &MoveData<'tcx>,
|
||||
//FIXME: this is not mutated, but expected to be modified as
|
||||
// out param, bug?
|
||||
dropped_at: &mut Vec<(Local, Location)>,
|
||||
) {
|
||||
debug!("populate_access_facts()");
|
||||
let location_table = typeck.borrowck_context.location_table;
|
||||
|
||||
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
|
||||
let mut extractor = UseFactsExtractor {
|
||||
|
|
@ -104,10 +101,6 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
|
|||
};
|
||||
extractor.visit_body(body);
|
||||
|
||||
facts.var_dropped_at.extend(
|
||||
dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))),
|
||||
);
|
||||
|
||||
for (local, local_decl) in body.local_decls.iter_enumerated() {
|
||||
debug!(
|
||||
"add use_of_var_derefs_origin facts - local={:?}, type={:?}",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
|||
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
||||
use crate::location::RichLocation;
|
||||
use crate::{
|
||||
region_infer::values::{self, LiveLoans},
|
||||
type_check::liveness::local_use_map::LocalUseMap,
|
||||
|
|
@ -46,7 +47,6 @@ pub(super) fn trace<'mir, 'tcx>(
|
|||
move_data: &MoveData<'tcx>,
|
||||
relevant_live_locals: Vec<Local>,
|
||||
boring_locals: Vec<Local>,
|
||||
polonius_drop_used: Option<Vec<(Local, Location)>>,
|
||||
) {
|
||||
let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body);
|
||||
|
||||
|
|
@ -93,9 +93,7 @@ pub(super) fn trace<'mir, 'tcx>(
|
|||
|
||||
let mut results = LivenessResults::new(cx);
|
||||
|
||||
if let Some(drop_used) = polonius_drop_used {
|
||||
results.add_extra_drop_facts(drop_used, relevant_live_locals.iter().copied().collect())
|
||||
}
|
||||
results.add_extra_drop_facts(&relevant_live_locals);
|
||||
|
||||
results.compute_for_all_locals(relevant_live_locals);
|
||||
|
||||
|
|
@ -218,21 +216,38 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
|||
///
|
||||
/// Add facts for all locals with free regions, since regions may outlive
|
||||
/// the function body only at certain nodes in the CFG.
|
||||
fn add_extra_drop_facts(
|
||||
&mut self,
|
||||
drop_used: Vec<(Local, Location)>,
|
||||
relevant_live_locals: FxIndexSet<Local>,
|
||||
) {
|
||||
fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) -> Option<()> {
|
||||
let drop_used = self
|
||||
.cx
|
||||
.typeck
|
||||
.borrowck_context
|
||||
.all_facts
|
||||
.as_ref()
|
||||
.map(|facts| facts.var_dropped_at.clone())?;
|
||||
|
||||
let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect();
|
||||
|
||||
let locations = IntervalSet::new(self.cx.elements.num_points());
|
||||
|
||||
for (local, location) in drop_used {
|
||||
for (local, location_index) in drop_used {
|
||||
if !relevant_live_locals.contains(&local) {
|
||||
let local_ty = self.cx.body.local_decls[local].ty;
|
||||
if local_ty.has_free_regions() {
|
||||
let location = match self
|
||||
.cx
|
||||
.typeck
|
||||
.borrowck_context
|
||||
.location_table
|
||||
.to_location(location_index)
|
||||
{
|
||||
RichLocation::Start(l) => l,
|
||||
RichLocation::Mid(l) => l,
|
||||
};
|
||||
self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// Clear the value of fields that are "per local variable".
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@ use rustc_middle::ty::adjustment::PointerCoercion;
|
|||
use rustc_middle::ty::cast::CastTy;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
|
||||
OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
|
||||
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
|
||||
Dynamic, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
use rustc_middle::ty::{GenericArgsRef, UserArgs};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
|
@ -188,15 +189,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output);
|
||||
checker.check_signature_annotation(body);
|
||||
|
||||
liveness::generate(
|
||||
&mut checker,
|
||||
body,
|
||||
elements,
|
||||
flow_inits,
|
||||
move_data,
|
||||
location_table,
|
||||
use_polonius,
|
||||
);
|
||||
liveness::generate(&mut checker, body, elements, flow_inits, move_data, use_polonius);
|
||||
|
||||
translate_outlives_facts(&mut checker);
|
||||
let opaque_type_values = infcx.take_opaque_types();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, T
|
|||
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{ErrorGuaranteed, Symbol};
|
||||
use std::cell::Cell;
|
||||
use std::iter;
|
||||
|
||||
use crate::renumber::RegionCtxt;
|
||||
|
|
@ -186,6 +187,10 @@ struct UniversalRegionIndices<'tcx> {
|
|||
|
||||
/// The vid assigned to `'static`. Used only for diagnostics.
|
||||
pub fr_static: RegionVid,
|
||||
|
||||
/// Whether we've encountered an error region. If we have, cancel all
|
||||
/// outlives errors, as they are likely bogus.
|
||||
pub tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
|
@ -408,6 +413,10 @@ impl<'tcx> UniversalRegions<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
self.indices.tainted_by_errors.get()
|
||||
}
|
||||
}
|
||||
|
||||
struct UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
|
|
@ -663,7 +672,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
|
||||
let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));
|
||||
|
||||
UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static }
|
||||
UniversalRegionIndices {
|
||||
indices: global_mapping.chain(arg_mapping).collect(),
|
||||
fr_static,
|
||||
tainted_by_errors: Cell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_inputs_and_output(
|
||||
|
|
@ -868,7 +881,8 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
|
|||
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
|
||||
if let ty::ReVar(..) = *r {
|
||||
r.as_var()
|
||||
} else if r.is_error() {
|
||||
} else if let ty::ReError(guar) = *r {
|
||||
self.tainted_by_errors.set(Some(guar));
|
||||
// We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
|
||||
// `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
|
||||
// errors are being emitted and 2) it leaves the happy path unaffected.
|
||||
|
|
|
|||
|
|
@ -288,6 +288,29 @@ fn produce_final_output_artifacts(
|
|||
}
|
||||
}
|
||||
|
||||
if sess.opts.json_artifact_notifications {
|
||||
if codegen_results.modules.len() == 1 {
|
||||
codegen_results.modules[0].for_each_output(|_path, ty| {
|
||||
if sess.opts.output_types.contains_key(&ty) {
|
||||
let descr = ty.shorthand();
|
||||
// for single cgu file is renamed to drop cgu specific suffix
|
||||
// so we regenerate it the same way
|
||||
let path = crate_output.path(ty);
|
||||
sess.dcx().emit_artifact_notification(path.as_path(), descr);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for module in &codegen_results.modules {
|
||||
module.for_each_output(|path, ty| {
|
||||
if sess.opts.output_types.contains_key(&ty) {
|
||||
let descr = ty.shorthand();
|
||||
sess.dcx().emit_artifact_notification(&path, descr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We leave the following files around by default:
|
||||
// - #crate#.o
|
||||
// - #crate#.crate.metadata.o
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeM
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
use rustc_target::abi::{
|
||||
self, Abi, Align, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ pub mod mcdc {
|
|||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct DecisionParameters {
|
||||
bitmap_idx: u32,
|
||||
conditions_num: u16,
|
||||
num_conditions: u16,
|
||||
}
|
||||
|
||||
// ConditionId in llvm is `unsigned int` at 18 while `int16_t` at [19](https://github.com/llvm/llvm-project/pull/81257)
|
||||
|
|
@ -177,8 +177,9 @@ pub mod mcdc {
|
|||
}
|
||||
|
||||
impl From<DecisionInfo> for DecisionParameters {
|
||||
fn from(value: DecisionInfo) -> Self {
|
||||
Self { bitmap_idx: value.bitmap_idx, conditions_num: value.conditions_num }
|
||||
fn from(info: DecisionInfo) -> Self {
|
||||
let DecisionInfo { bitmap_idx, num_conditions } = info;
|
||||
Self { bitmap_idx, num_conditions }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
|
||||
self, AdtKind, CoroutineArgsExt, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt,
|
||||
Visibility,
|
||||
};
|
||||
use rustc_session::config::{self, DebugInfo, Lto};
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_middle::{
|
|||
ty::{
|
||||
self,
|
||||
layout::{LayoutOf, TyAndLayout},
|
||||
AdtDef, CoroutineArgs, Ty,
|
||||
AdtDef, CoroutineArgs, CoroutineArgsExt, Ty,
|
||||
},
|
||||
};
|
||||
use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_middle::{
|
|||
ty::{
|
||||
self,
|
||||
layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
|
||||
AdtDef, CoroutineArgs, Ty, VariantDef,
|
||||
AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef,
|
||||
},
|
||||
};
|
||||
use rustc_span::Symbol;
|
||||
|
|
|
|||
|
|
@ -482,8 +482,60 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
_ if name.as_str().starts_with("simd_") => {
|
||||
// Unpack non-power-of-2 #[repr(packed, simd)] arguments.
|
||||
// This gives them the expected layout of a regular #[repr(simd)] vector.
|
||||
let mut loaded_args = Vec::new();
|
||||
for (ty, arg) in arg_tys.iter().zip(args) {
|
||||
loaded_args.push(
|
||||
// #[repr(packed, simd)] vectors are passed like arrays (as references,
|
||||
// with reduced alignment and no padding) rather than as immediates.
|
||||
// We can use a vector load to fix the layout and turn the argument
|
||||
// into an immediate.
|
||||
if ty.is_simd()
|
||||
&& let OperandValue::Ref(place) = arg.val
|
||||
{
|
||||
let (size, elem_ty) = ty.simd_size_and_type(self.tcx());
|
||||
let elem_ll_ty = match elem_ty.kind() {
|
||||
ty::Float(f) => self.type_float_from_ty(*f),
|
||||
ty::Int(i) => self.type_int_from_ty(*i),
|
||||
ty::Uint(u) => self.type_uint_from_ty(*u),
|
||||
ty::RawPtr(_, _) => self.type_ptr(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let loaded =
|
||||
self.load_from_place(self.type_vector(elem_ll_ty, size), place);
|
||||
OperandRef::from_immediate_or_packed_pair(self, loaded, arg.layout)
|
||||
} else {
|
||||
*arg
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let llret_ty = if ret_ty.is_simd()
|
||||
&& let abi::Abi::Aggregate { .. } = self.layout_of(ret_ty).layout.abi
|
||||
{
|
||||
let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx());
|
||||
let elem_ll_ty = match elem_ty.kind() {
|
||||
ty::Float(f) => self.type_float_from_ty(*f),
|
||||
ty::Int(i) => self.type_int_from_ty(*i),
|
||||
ty::Uint(u) => self.type_uint_from_ty(*u),
|
||||
ty::RawPtr(_, _) => self.type_ptr(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.type_vector(elem_ll_ty, size)
|
||||
} else {
|
||||
llret_ty
|
||||
};
|
||||
|
||||
match generic_simd_intrinsic(
|
||||
self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span,
|
||||
self,
|
||||
name,
|
||||
callee_ty,
|
||||
fn_args,
|
||||
&loaded_args,
|
||||
ret_ty,
|
||||
llret_ty,
|
||||
span,
|
||||
) {
|
||||
Ok(llval) => llval,
|
||||
Err(()) => return Ok(()),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_codegen_ssa::traits::*;
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape};
|
||||
use rustc_target::abi::{Float, Int, Pointer};
|
||||
use rustc_target::abi::{Scalar, Size, Variants};
|
||||
|
|
|
|||
|
|
@ -717,6 +717,29 @@ fn produce_final_output_artifacts(
|
|||
}
|
||||
}
|
||||
|
||||
if sess.opts.json_artifact_notifications {
|
||||
if compiled_modules.modules.len() == 1 {
|
||||
compiled_modules.modules[0].for_each_output(|_path, ty| {
|
||||
if sess.opts.output_types.contains_key(&ty) {
|
||||
let descr = ty.shorthand();
|
||||
// for single cgu file is renamed to drop cgu specific suffix
|
||||
// so we regenerate it the same way
|
||||
let path = crate_output.path(ty);
|
||||
sess.dcx().emit_artifact_notification(path.as_path(), descr);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for module in &compiled_modules.modules {
|
||||
module.for_each_output(|path, ty| {
|
||||
if sess.opts.output_types.contains_key(&ty) {
|
||||
let descr = ty.shorthand();
|
||||
sess.dcx().emit_artifact_notification(&path, descr);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We leave the following files around by default:
|
||||
// - #crate#.o
|
||||
// - #crate#.crate.metadata.o
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ fn push_debuginfo_type_name<'tcx>(
|
|||
let ExistentialProjection { def_id: item_def_id, term, .. } =
|
||||
tcx.instantiate_bound_regions_with_erased(bound);
|
||||
// FIXME(associated_const_equality): allow for consts here
|
||||
(item_def_id, term.ty().unwrap())
|
||||
(item_def_id, term.expect_type())
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,24 @@ pub struct CompiledModule {
|
|||
pub llvm_ir: Option<PathBuf>, // --emit=llvm-ir, llvm-bc is in bytecode
|
||||
}
|
||||
|
||||
impl CompiledModule {
|
||||
/// Call `emit` function with every artifact type currently compiled
|
||||
pub fn for_each_output(&self, mut emit: impl FnMut(&Path, OutputType)) {
|
||||
if let Some(path) = self.object.as_deref() {
|
||||
emit(path, OutputType::Object);
|
||||
}
|
||||
if let Some(path) = self.bytecode.as_deref() {
|
||||
emit(path, OutputType::Bitcode);
|
||||
}
|
||||
if let Some(path) = self.llvm_ir.as_deref() {
|
||||
emit(path, OutputType::LlvmAssembly);
|
||||
}
|
||||
if let Some(path) = self.assembly.as_deref() {
|
||||
emit(path, OutputType::Assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CachedModuleCodegen {
|
||||
pub name: String,
|
||||
pub source: WorkProduct,
|
||||
|
|
|
|||
|
|
@ -735,7 +735,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
// which path expressions are getting called on and which path expressions are only used
|
||||
// as function pointers. This is required for correctness.
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
|
||||
let cause = ObligationCause::new(
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
|||
if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
|
||||
let constraint = with_no_trimmed_paths!(format!(
|
||||
"~const {}",
|
||||
trait_ref.print_only_trait_path()
|
||||
trait_ref.print_trait_sugared(),
|
||||
));
|
||||
suggest_constraining_type_param(
|
||||
tcx,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use rustc_middle::mir;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
|
||||
use rustc_middle::ty::{self, ScalarInt, Ty};
|
||||
use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty};
|
||||
use rustc_target::abi::{self, TagEncoding};
|
||||
use rustc_target::abi::{VariantIdx, Variants};
|
||||
use tracing::{instrument, trace};
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ fn dominators_impl<G: ControlFlowGraph>(graph: &G) -> Inner<G::Node> {
|
|||
// These are all done here rather than through one of the 'standard'
|
||||
// graph traversals to help make this fast.
|
||||
'recurse: while let Some(frame) = stack.last_mut() {
|
||||
while let Some(successor) = frame.iter.next() {
|
||||
for successor in frame.iter.by_ref() {
|
||||
if real_to_pre_order[successor].is_none() {
|
||||
let pre_order_idx = pre_order_to_real.push(successor);
|
||||
real_to_pre_order[successor] = Some(pre_order_idx);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ fn post_order_walk<G: DirectedGraph + Successors>(
|
|||
let node = frame.node;
|
||||
visited[node] = true;
|
||||
|
||||
while let Some(successor) = frame.iter.next() {
|
||||
for successor in frame.iter.by_ref() {
|
||||
if !visited[successor] {
|
||||
stack.push(PostOrderFrame { node: successor, iter: graph.successors(successor) });
|
||||
continue 'recurse;
|
||||
|
|
@ -112,7 +112,7 @@ where
|
|||
/// This is equivalent to just invoke `next` repeatedly until
|
||||
/// you get a `None` result.
|
||||
pub fn complete_search(&mut self) {
|
||||
while let Some(_) = self.next() {}
|
||||
for _ in self.by_ref() {}
|
||||
}
|
||||
|
||||
/// Returns true if node has been visited thus far.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ pub struct SccData<S: Idx> {
|
|||
}
|
||||
|
||||
impl<N: Idx, S: Idx + Ord> Sccs<N, S> {
|
||||
pub fn new(graph: &(impl DirectedGraph<Node = N> + Successors)) -> Self {
|
||||
pub fn new(graph: &impl Successors<Node = N>) -> Self {
|
||||
SccsConstruction::construct(graph)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -562,7 +562,7 @@ impl SelfProfiler {
|
|||
// ASLR is disabled and the heap is otherwise deterministic.
|
||||
let pid: u32 = process::id();
|
||||
let filename = format!("{crate_name}-{pid:07}.rustc_profile");
|
||||
let path = output_directory.join(&filename);
|
||||
let path = output_directory.join(filename);
|
||||
let profiler =
|
||||
Profiler::with_counter(&path, measureme::counters::Counter::by_name(counter_name)?)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -125,13 +125,13 @@ impl<K: Ord, V> SortedMap<K, V> {
|
|||
|
||||
/// Iterate over the keys, sorted
|
||||
#[inline]
|
||||
pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator + DoubleEndedIterator {
|
||||
pub fn keys(&self) -> impl ExactSizeIterator<Item = &K> + DoubleEndedIterator {
|
||||
self.data.iter().map(|(k, _)| k)
|
||||
}
|
||||
|
||||
/// Iterate over values, sorted by key
|
||||
#[inline]
|
||||
pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator + DoubleEndedIterator {
|
||||
pub fn values(&self) -> impl ExactSizeIterator<Item = &V> + DoubleEndedIterator {
|
||||
self.data.iter().map(|(_, v)| v)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ mod maybe_sync {
|
|||
match self.mode {
|
||||
Mode::NoSync => {
|
||||
let cell = unsafe { &self.lock.mode_union.no_sync };
|
||||
debug_assert_eq!(cell.get(), true);
|
||||
debug_assert!(cell.get());
|
||||
cell.set(false);
|
||||
}
|
||||
// SAFETY (unlock): We know that the lock is locked as this type is a proof of that.
|
||||
|
|
|
|||
|
|
@ -814,13 +814,17 @@ fn print_crate_info(
|
|||
match expected_values {
|
||||
ExpectedValues::Any => check_cfgs.push(format!("{name}=any()")),
|
||||
ExpectedValues::Some(values) => {
|
||||
check_cfgs.extend(values.iter().map(|value| {
|
||||
if let Some(value) = value {
|
||||
format!("{name}=\"{value}\"")
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
}))
|
||||
if !values.is_empty() {
|
||||
check_cfgs.extend(values.iter().map(|value| {
|
||||
if let Some(value) = value {
|
||||
format!("{name}=\"{value}\"")
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
check_cfgs.push(format!("{name}="))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast_pretty::pprust as pprust_ast;
|
||||
use rustc_errors::FatalError;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir_pretty as pprust_hir;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
|
||||
|
|
@ -70,11 +69,7 @@ struct HirIdentifiedAnn<'tcx> {
|
|||
|
||||
impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> {
|
||||
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
|
||||
pprust_hir::PpAnn::nested(
|
||||
&(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>),
|
||||
state,
|
||||
nested,
|
||||
)
|
||||
self.tcx.nested(state, nested)
|
||||
}
|
||||
|
||||
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
|
||||
|
|
@ -152,8 +147,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> {
|
|||
if let pprust_hir::Nested::Body(id) = nested {
|
||||
self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id)));
|
||||
}
|
||||
let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
|
||||
pprust_hir::PpAnn::nested(pp_ann, state, nested);
|
||||
self.tcx.nested(state, nested);
|
||||
self.maybe_typeck_results.set(old_maybe_typeck_results);
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +163,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> {
|
|||
self.tcx
|
||||
.hir()
|
||||
.maybe_body_owned_by(expr.hir_id.owner.def_id)
|
||||
.map(|body_id| self.tcx.typeck_body(body_id))
|
||||
.map(|body_id| self.tcx.typeck_body(body_id.id()))
|
||||
});
|
||||
|
||||
if let Some(typeck_results) = typeck_results {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
An associated type binding was done outside of the type parameter declaration
|
||||
and `where` clause.
|
||||
An associated item constraint was written in an unexpected context.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
|
@ -16,12 +15,12 @@ impl Foo for isize {
|
|||
fn boo(&self) -> usize { 42 }
|
||||
}
|
||||
|
||||
fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
|
||||
// error: associated type bindings are not allowed here
|
||||
fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
|
||||
// error: associated item constraint are not allowed here
|
||||
```
|
||||
|
||||
To solve this error, please move the type bindings in the type parameter
|
||||
declaration:
|
||||
To solve this error, please move the associated item constraints to the type
|
||||
parameter declaration:
|
||||
|
||||
```
|
||||
# struct Bar;
|
||||
|
|
@ -29,7 +28,7 @@ declaration:
|
|||
fn baz<I: Foo<A=Bar>>(x: &<I as Foo>::A) {} // ok!
|
||||
```
|
||||
|
||||
Or in the `where` clause:
|
||||
Or into the where-clause:
|
||||
|
||||
```
|
||||
# struct Bar;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ declare_features! (
|
|||
(accepted, copy_closures, "1.26.0", Some(44490)),
|
||||
/// Allows `crate` in paths.
|
||||
(accepted, crate_in_paths, "1.30.0", Some(45477)),
|
||||
/// Allows users to provide classes for fenced code block using `class:classname`.
|
||||
(accepted, custom_code_classes_in_docs, "CURRENT_RUSTC_VERSION", Some(79483)),
|
||||
/// Allows using `#[debugger_visualizer]` attribute.
|
||||
(accepted, debugger_visualizer, "1.71.0", Some(95939)),
|
||||
/// Allows rustc to inject a default alloc_error_handler
|
||||
|
|
|
|||
|
|
@ -578,6 +578,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
"rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
|
||||
through unstable paths"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_deprecated_safe_2024, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::Yes,
|
||||
"rustc_deprecated_safe_2024 is supposed to be used in libstd only",
|
||||
),
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes: Type system related:
|
||||
|
|
|
|||
|
|
@ -177,8 +177,6 @@ declare_features! (
|
|||
|
||||
/// Allows using the `unadjusted` ABI; perma-unstable.
|
||||
(internal, abi_unadjusted, "1.16.0", None),
|
||||
/// Allows using the `vectorcall` ABI.
|
||||
(unstable, abi_vectorcall, "1.7.0", None),
|
||||
/// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`.
|
||||
(internal, allocator_internals, "1.20.0", None),
|
||||
/// Allows using `#[allow_internal_unsafe]`. This is an
|
||||
|
|
@ -243,6 +241,8 @@ declare_features! (
|
|||
// feature-group-start: internal feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/// Allows using the `vectorcall` ABI.
|
||||
(unstable, abi_vectorcall, "1.7.0", Some(124485)),
|
||||
/// Allows features specific to auto traits.
|
||||
/// Renamed from `optin_builtin_traits`.
|
||||
(unstable, auto_traits, "1.50.0", Some(13231)),
|
||||
|
|
@ -424,8 +424,6 @@ declare_features! (
|
|||
/// Allows function attribute `#[coverage(on/off)]`, to control coverage
|
||||
/// instrumentation of that function.
|
||||
(unstable, coverage_attribute, "1.74.0", Some(84605)),
|
||||
/// Allows users to provide classes for fenced code block using `class:classname`.
|
||||
(unstable, custom_code_classes_in_docs, "1.74.0", Some(79483)),
|
||||
/// Allows non-builtin attributes in inner attribute position.
|
||||
(unstable, custom_inner_attributes, "1.30.0", Some(54726)),
|
||||
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
|
||||
|
|
|
|||
|
|
@ -300,23 +300,30 @@ impl GenericArg<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The generic arguments and associated item constraints of a path segment.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct GenericArgs<'hir> {
|
||||
/// The generic arguments for this path segment.
|
||||
pub args: &'hir [GenericArg<'hir>],
|
||||
/// Bindings (equality constraints) on associated types, if present.
|
||||
/// E.g., `Foo<A = Bar>`.
|
||||
pub bindings: &'hir [TypeBinding<'hir>],
|
||||
/// Were arguments written in parenthesized form `Fn(T) -> U`?
|
||||
/// The associated item constraints for this path segment.
|
||||
pub constraints: &'hir [AssocItemConstraint<'hir>],
|
||||
/// Whether the arguments were written in parenthesized form (e.g., `Fn(T) -> U`).
|
||||
///
|
||||
/// This is required mostly for pretty-printing and diagnostics,
|
||||
/// but also for changing lifetime elision rules to be "function-like".
|
||||
pub parenthesized: GenericArgsParentheses,
|
||||
/// The span encompassing arguments and the surrounding brackets `<>` or `()`
|
||||
/// The span encompassing the arguments, constraints and the surrounding brackets (`<>` or `()`).
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// Foo<A, B, AssocTy = D> Fn(T, U, V) -> W
|
||||
/// ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
|
||||
/// ```
|
||||
///
|
||||
/// Note that this may be:
|
||||
/// - empty, if there are no generic brackets (but there may be hidden lifetimes)
|
||||
/// - dummy, if this was generated while desugaring
|
||||
/// - dummy, if this was generated during desugaring
|
||||
pub span_ext: Span,
|
||||
}
|
||||
|
||||
|
|
@ -324,39 +331,63 @@ impl<'hir> GenericArgs<'hir> {
|
|||
pub const fn none() -> Self {
|
||||
Self {
|
||||
args: &[],
|
||||
bindings: &[],
|
||||
constraints: &[],
|
||||
parenthesized: GenericArgsParentheses::No,
|
||||
span_ext: DUMMY_SP,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inputs(&self) -> &[Ty<'hir>] {
|
||||
if self.parenthesized == GenericArgsParentheses::ParenSugar {
|
||||
for arg in self.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(_) => {}
|
||||
GenericArg::Type(ref ty) => {
|
||||
if let TyKind::Tup(ref tys) = ty.kind {
|
||||
return tys;
|
||||
}
|
||||
break;
|
||||
}
|
||||
GenericArg::Const(_) => {}
|
||||
GenericArg::Infer(_) => {}
|
||||
}
|
||||
}
|
||||
/// Obtain the list of input types and the output type if the generic arguments are parenthesized.
|
||||
///
|
||||
/// Returns the `Ty0, Ty1, ...` and the `RetTy` in `Trait(Ty0, Ty1, ...) -> RetTy`.
|
||||
/// Panics if the parenthesized arguments have an incorrect form (this shouldn't happen).
|
||||
pub fn paren_sugar_inputs_output(&self) -> Option<(&[Ty<'hir>], &Ty<'hir>)> {
|
||||
if self.parenthesized != GenericArgsParentheses::ParenSugar {
|
||||
return None;
|
||||
}
|
||||
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
|
||||
|
||||
let inputs = self
|
||||
.args
|
||||
.iter()
|
||||
.find_map(|arg| {
|
||||
let GenericArg::Type(ty) = arg else { return None };
|
||||
let TyKind::Tup(tys) = &ty.kind else { return None };
|
||||
Some(tys)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Some((inputs, self.paren_sugar_output_inner()))
|
||||
}
|
||||
|
||||
pub fn has_err(&self) -> bool {
|
||||
self.args.iter().any(|arg| match arg {
|
||||
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)),
|
||||
_ => false,
|
||||
}) || self.bindings.iter().any(|arg| match arg.kind {
|
||||
TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err(_)),
|
||||
_ => false,
|
||||
})
|
||||
/// Obtain the output type if the generic arguments are parenthesized.
|
||||
///
|
||||
/// Returns the `RetTy` in `Trait(Ty0, Ty1, ...) -> RetTy`.
|
||||
/// Panics if the parenthesized arguments have an incorrect form (this shouldn't happen).
|
||||
pub fn paren_sugar_output(&self) -> Option<&Ty<'hir>> {
|
||||
(self.parenthesized == GenericArgsParentheses::ParenSugar)
|
||||
.then(|| self.paren_sugar_output_inner())
|
||||
}
|
||||
|
||||
fn paren_sugar_output_inner(&self) -> &Ty<'hir> {
|
||||
let [constraint] = self.constraints.try_into().unwrap();
|
||||
debug_assert_eq!(constraint.ident.name, sym::Output);
|
||||
constraint.ty().unwrap()
|
||||
}
|
||||
|
||||
pub fn has_err(&self) -> Option<ErrorGuaranteed> {
|
||||
self.args
|
||||
.iter()
|
||||
.find_map(|arg| {
|
||||
let GenericArg::Type(ty) = arg else { return None };
|
||||
let TyKind::Err(guar) = ty.kind else { return None };
|
||||
Some(guar)
|
||||
})
|
||||
.or_else(|| {
|
||||
self.constraints.iter().find_map(|constraint| {
|
||||
let TyKind::Err(guar) = constraint.ty()?.kind else { return None };
|
||||
Some(guar)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -383,9 +414,11 @@ impl<'hir> GenericArgs<'hir> {
|
|||
.count()
|
||||
}
|
||||
|
||||
/// The span encompassing the text inside the surrounding brackets.
|
||||
/// It will also include bindings if they aren't in the form `-> Ret`
|
||||
/// Returns `None` if the span is empty (e.g. no brackets) or dummy
|
||||
/// The span encompassing the arguments and constraints[^1] inside the surrounding brackets.
|
||||
///
|
||||
/// Returns `None` if the span is empty (i.e., no brackets) or dummy.
|
||||
///
|
||||
/// [^1]: Unless of the form `-> Ty` (see [`GenericArgsParentheses`]).
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
let span_ext = self.span_ext()?;
|
||||
Some(span_ext.with_lo(span_ext.lo() + BytePos(1)).with_hi(span_ext.hi() - BytePos(1)))
|
||||
|
|
@ -660,9 +693,7 @@ impl<'hir> Generics<'hir> {
|
|||
|bound| {
|
||||
let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref()
|
||||
&& let [.., segment] = trait_ref.path.segments
|
||||
&& segment.args().parenthesized == GenericArgsParentheses::ParenSugar
|
||||
&& let [binding] = segment.args().bindings
|
||||
&& let TypeBindingKind::Equality { term: Term::Ty(ret_ty) } = binding.kind
|
||||
&& let Some(ret_ty) = segment.args().paren_sugar_output()
|
||||
&& let ret_ty = ret_ty.peel_refs()
|
||||
&& let TyKind::TraitObject(
|
||||
_,
|
||||
|
|
@ -748,7 +779,7 @@ impl<'hir> Generics<'hir> {
|
|||
/// A single predicate in a where-clause.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum WherePredicate<'hir> {
|
||||
/// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
|
||||
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
|
||||
BoundPredicate(WhereBoundPredicate<'hir>),
|
||||
/// A lifetime predicate (e.g., `'a: 'b + 'c`).
|
||||
RegionPredicate(WhereRegionPredicate<'hir>),
|
||||
|
|
@ -2356,24 +2387,43 @@ pub enum ImplItemKind<'hir> {
|
|||
Type(&'hir Ty<'hir>),
|
||||
}
|
||||
|
||||
/// An associated item binding.
|
||||
/// A constraint on an associated item.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// * `Trait<A = Ty, B = Ty>`
|
||||
/// * `Trait<G<Ty> = Ty>`
|
||||
/// * `Trait<A: Bound>`
|
||||
/// * `Trait<C = { Ct }>` (under feature `associated_const_equality`)
|
||||
/// * `Trait<f(): Bound>` (under feature `return_type_notation`)
|
||||
/// * the `A = Ty` and `B = Ty` in `Trait<A = Ty, B = Ty>`
|
||||
/// * the `G<Ty> = Ty` in `Trait<G<Ty> = Ty>`
|
||||
/// * the `A: Bound` in `Trait<A: Bound>`
|
||||
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
|
||||
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
|
||||
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct TypeBinding<'hir> {
|
||||
pub struct AssocItemConstraint<'hir> {
|
||||
pub hir_id: HirId,
|
||||
pub ident: Ident,
|
||||
pub gen_args: &'hir GenericArgs<'hir>,
|
||||
pub kind: TypeBindingKind<'hir>,
|
||||
pub kind: AssocItemConstraintKind<'hir>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'hir> AssocItemConstraint<'hir> {
|
||||
/// Obtain the type on the RHS of an assoc ty equality constraint if applicable.
|
||||
pub fn ty(self) -> Option<&'hir Ty<'hir>> {
|
||||
match self.kind {
|
||||
AssocItemConstraintKind::Equality { term: Term::Ty(ty) } => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtain the const on the RHS of an assoc const equality constraint if applicable.
|
||||
pub fn ct(self) -> Option<&'hir AnonConst> {
|
||||
match self.kind {
|
||||
AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum Term<'hir> {
|
||||
Ty(&'hir Ty<'hir>),
|
||||
|
|
@ -2392,28 +2442,18 @@ impl<'hir> From<&'hir AnonConst> for Term<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
// Represents the two kinds of type bindings.
|
||||
/// The kind of [associated item constraint][AssocItemConstraint].
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum TypeBindingKind<'hir> {
|
||||
/// E.g., `Foo<Bar: Send>`.
|
||||
Constraint { bounds: &'hir [GenericBound<'hir>] },
|
||||
/// E.g., `Foo<Bar = ()>`.
|
||||
pub enum AssocItemConstraintKind<'hir> {
|
||||
/// An equality constraint for an associated item (e.g., `AssocTy = Ty` in `Trait<AssocTy = Ty>`).
|
||||
///
|
||||
/// Also known as an *associated item binding* (we *bind* an associated item to a term).
|
||||
///
|
||||
/// Furthermore, associated type equality constraints can also be referred to as *associated type
|
||||
/// bindings*. Similarly with associated const equality constraints and *associated const bindings*.
|
||||
Equality { term: Term<'hir> },
|
||||
}
|
||||
|
||||
impl TypeBinding<'_> {
|
||||
pub fn ty(&self) -> &Ty<'_> {
|
||||
match self.kind {
|
||||
TypeBindingKind::Equality { term: Term::Ty(ref ty) } => ty,
|
||||
_ => panic!("expected equality type binding for parenthesized generic args"),
|
||||
}
|
||||
}
|
||||
pub fn opt_const(&self) -> Option<&'_ AnonConst> {
|
||||
match self.kind {
|
||||
TypeBindingKind::Equality { term: Term::Const(ref c) } => Some(c),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
/// A bound on an associated type (e.g., `AssocTy: Bound` in `Trait<AssocTy: Bound>`).
|
||||
Bound { bounds: &'hir [GenericBound<'hir>] },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
|
|
@ -3609,7 +3649,7 @@ pub enum Node<'hir> {
|
|||
Stmt(&'hir Stmt<'hir>),
|
||||
PathSegment(&'hir PathSegment<'hir>),
|
||||
Ty(&'hir Ty<'hir>),
|
||||
TypeBinding(&'hir TypeBinding<'hir>),
|
||||
AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
|
||||
TraitRef(&'hir TraitRef<'hir>),
|
||||
Pat(&'hir Pat<'hir>),
|
||||
PatField(&'hir PatField<'hir>),
|
||||
|
|
@ -3658,7 +3698,7 @@ impl<'hir> Node<'hir> {
|
|||
| Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
|
||||
Node::Lifetime(lt) => Some(lt.ident),
|
||||
Node::GenericParam(p) => Some(p.name.ident()),
|
||||
Node::TypeBinding(b) => Some(b.ident),
|
||||
Node::AssocItemConstraint(c) => Some(c.ident),
|
||||
Node::PatField(f) => Some(f.ident),
|
||||
Node::ExprField(f) => Some(f.ident),
|
||||
Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
|
||||
|
|
@ -3834,7 +3874,7 @@ impl<'hir> Node<'hir> {
|
|||
expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n;
|
||||
expect_path_segment, &'hir PathSegment<'hir>, Node::PathSegment(n), n;
|
||||
expect_ty, &'hir Ty<'hir>, Node::Ty(n), n;
|
||||
expect_type_binding, &'hir TypeBinding<'hir>, Node::TypeBinding(n), n;
|
||||
expect_assoc_item_constraint, &'hir AssocItemConstraint<'hir>, Node::AssocItemConstraint(n), n;
|
||||
expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n;
|
||||
expect_pat, &'hir Pat<'hir>, Node::Pat(n), n;
|
||||
expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n;
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ pub trait Visitor<'v>: Sized {
|
|||
walk_item(self, i)
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, b: &'v Body<'v>) -> Self::Result {
|
||||
fn visit_body(&mut self, b: &Body<'v>) -> Self::Result {
|
||||
walk_body(self, b)
|
||||
}
|
||||
|
||||
|
|
@ -453,8 +453,11 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) -> Self::Result {
|
||||
walk_generic_args(self, generic_args)
|
||||
}
|
||||
fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) -> Self::Result {
|
||||
walk_assoc_type_binding(self, type_binding)
|
||||
fn visit_assoc_item_constraint(
|
||||
&mut self,
|
||||
constraint: &'v AssocItemConstraint<'v>,
|
||||
) -> Self::Result {
|
||||
walk_assoc_item_constraint(self, constraint)
|
||||
}
|
||||
fn visit_attribute(&mut self, _attr: &'v Attribute) -> Self::Result {
|
||||
Self::Result::output()
|
||||
|
|
@ -578,7 +581,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
|||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) -> V::Result {
|
||||
pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &Body<'v>) -> V::Result {
|
||||
walk_list!(visitor, visit_param, body.params);
|
||||
visitor.visit_expr(body.value)
|
||||
}
|
||||
|
|
@ -1248,23 +1251,25 @@ pub fn walk_generic_args<'v, V: Visitor<'v>>(
|
|||
generic_args: &'v GenericArgs<'v>,
|
||||
) -> V::Result {
|
||||
walk_list!(visitor, visit_generic_arg, generic_args.args);
|
||||
walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings);
|
||||
walk_list!(visitor, visit_assoc_item_constraint, generic_args.constraints);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
|
||||
pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
|
||||
visitor: &mut V,
|
||||
type_binding: &'v TypeBinding<'v>,
|
||||
constraint: &'v AssocItemConstraint<'v>,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_id(type_binding.hir_id));
|
||||
try_visit!(visitor.visit_ident(type_binding.ident));
|
||||
try_visit!(visitor.visit_generic_args(type_binding.gen_args));
|
||||
match type_binding.kind {
|
||||
TypeBindingKind::Equality { ref term } => match term {
|
||||
try_visit!(visitor.visit_id(constraint.hir_id));
|
||||
try_visit!(visitor.visit_ident(constraint.ident));
|
||||
try_visit!(visitor.visit_generic_args(constraint.gen_args));
|
||||
match constraint.kind {
|
||||
AssocItemConstraintKind::Equality { ref term } => match term {
|
||||
Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
|
||||
Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)),
|
||||
},
|
||||
TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds),
|
||||
AssocItemConstraintKind::Bound { bounds } => {
|
||||
walk_list!(visitor, visit_param_bound, bounds)
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ language_item_table! {
|
|||
AsyncDropSlice, sym::async_drop_slice, async_drop_slice_fn, Target::Fn, GenericRequirement::Exact(1);
|
||||
AsyncDropChain, sym::async_drop_chain, async_drop_chain_fn, Target::Fn, GenericRequirement::Exact(2);
|
||||
AsyncDropNoop, sym::async_drop_noop, async_drop_noop_fn, Target::Fn, GenericRequirement::Exact(0);
|
||||
AsyncDropDeferredDropInPlace, sym::async_drop_deferred_drop_in_place, async_drop_deferred_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
|
||||
AsyncDropFuse, sym::async_drop_fuse, async_drop_fuse_fn, Target::Fn, GenericRequirement::Exact(1);
|
||||
AsyncDropDefer, sym::async_drop_defer, async_drop_defer_fn, Target::Fn, GenericRequirement::Exact(1);
|
||||
AsyncDropEither, sym::async_drop_either, async_drop_either_fn, Target::Fn, GenericRequirement::Exact(3);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_
|
|||
hir_analysis_ambiguous_lifetime_bound =
|
||||
ambiguous lifetime bound, explicit lifetime bound required
|
||||
|
||||
hir_analysis_assoc_item_constraints_not_allowed_here =
|
||||
associated item constraints are not allowed here
|
||||
.label = associated item constraint not allowed here
|
||||
|
||||
hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}`
|
||||
|
||||
hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named ->
|
||||
|
|
@ -24,10 +28,6 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
|
|||
|
||||
hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here
|
||||
|
||||
hir_analysis_assoc_type_binding_not_allowed =
|
||||
associated type bindings are not allowed here
|
||||
.label = associated type not allowed here
|
||||
|
||||
hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
|
||||
.suggestion = use a fully qualified path with inferred lifetimes
|
||||
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
let param_env = tcx.param_env(defining_use_anchor);
|
||||
|
||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let args = match *origin {
|
||||
hir::OpaqueTyOrigin::FnReturn(parent)
|
||||
|
|
@ -1727,7 +1727,7 @@ pub(super) fn check_coroutine_obligations(
|
|||
.with_opaque_type_inference(def_id)
|
||||
.build();
|
||||
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
|
||||
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_hir::intravisit;
|
|||
use rustc_hir::{GenericParamKind, ImplItemKind};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::{util, FulfillmentError};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::util::ExplicitSelf;
|
||||
|
|
@ -25,7 +25,7 @@ use rustc_trait_selection::regions::InferCtxtRegionExt;
|
|||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
|
||||
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::iter;
|
||||
|
|
@ -225,7 +225,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
|
||||
|
||||
|
|
@ -493,7 +493,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
);
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
// Normalize the impl signature with fresh variables for lifetime inference.
|
||||
let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
|
||||
|
|
@ -764,17 +764,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
Ok(&*tcx.arena.alloc(remapped_types))
|
||||
}
|
||||
|
||||
struct ImplTraitInTraitCollector<'a, 'tcx> {
|
||||
ocx: &'a ObligationCtxt<'a, 'tcx>,
|
||||
struct ImplTraitInTraitCollector<'a, 'tcx, E> {
|
||||
ocx: &'a ObligationCtxt<'a, 'tcx, E>,
|
||||
types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
|
||||
span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: LocalDefId,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
|
||||
impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
|
||||
where
|
||||
E: 'tcx,
|
||||
{
|
||||
fn new(
|
||||
ocx: &'a ObligationCtxt<'a, 'tcx>,
|
||||
ocx: &'a ObligationCtxt<'a, 'tcx, E>,
|
||||
span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: LocalDefId,
|
||||
|
|
@ -783,7 +786,10 @@ impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
|
||||
impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
|
||||
where
|
||||
E: 'tcx,
|
||||
{
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.ocx.infcx.tcx
|
||||
}
|
||||
|
|
@ -1777,7 +1783,7 @@ fn compare_const_predicate_entailment<'tcx>(
|
|||
);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
|
||||
for (predicate, span) in impl_ct_own_bounds {
|
||||
|
|
@ -1910,7 +1916,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
|
||||
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
|
||||
|
||||
|
|
@ -1977,7 +1983,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
|
||||
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
|
||||
|
|
@ -2026,10 +2032,19 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
// to its definition type. This should be the param-env we use to *prove* the
|
||||
// predicate too, but we don't do that because of performance issues.
|
||||
// See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>.
|
||||
let trait_projection_ty = Ty::new_projection(tcx, trait_ty.def_id, rebased_args);
|
||||
let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
|
||||
let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
|
||||
for mut obligation in util::elaborate(tcx, obligations) {
|
||||
let normalized_predicate =
|
||||
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
|
||||
let normalized_predicate = if infcx.next_trait_solver() {
|
||||
obligation.predicate.fold_with(&mut ReplaceTy {
|
||||
tcx,
|
||||
from: trait_projection_ty,
|
||||
to: impl_identity_ty,
|
||||
})
|
||||
} else {
|
||||
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate)
|
||||
};
|
||||
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
|
||||
obligation.predicate = normalized_predicate;
|
||||
|
||||
|
|
@ -2050,6 +2065,22 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
|
||||
}
|
||||
|
||||
struct ReplaceTy<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
from: Ty<'tcx>,
|
||||
to: Ty<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceTy<'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if self.from == ty { self.to } else { ty.super_fold_with(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Install projection predicates that allow GATs to project to their own
|
||||
/// definition types. This is not allowed in general in cases of default
|
||||
/// associated types in trait definitions, or when specialization is involved,
|
||||
|
|
@ -2250,7 +2281,7 @@ fn try_report_async_mismatch<'tcx>(
|
|||
&& let Some(proj) = proj.no_bound_vars()
|
||||
&& infcx.can_eq(
|
||||
error.root_obligation.param_env,
|
||||
proj.term.ty().unwrap(),
|
||||
proj.term.expect_type(),
|
||||
impl_sig.output(),
|
||||
)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
|
|||
.explicit_item_bounds(future_ty.def_id)
|
||||
.iter_instantiated_copied(tcx, future_ty.args)
|
||||
.find_map(|(clause, _)| match clause.kind().no_bound_vars()? {
|
||||
ty::ClauseKind::Projection(proj) => proj.term.ty(),
|
||||
ty::ClauseKind::Projection(proj) => proj.term.as_type(),
|
||||
_ => None,
|
||||
})
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
adt_to_impl_args: GenericArgsRef<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
// Take the param-env of the adt and instantiate the args that show up in
|
||||
// the implementation's self type. This gives us the assumptions that the
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
|||
main_diagnostics_def_id,
|
||||
ObligationCauseCode::MainFunctionType,
|
||||
);
|
||||
let ocx = traits::ObligationCtxt::new(&infcx);
|
||||
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
|
||||
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
wfcheck::provide(providers);
|
||||
*providers = Providers {
|
||||
adt_destructor,
|
||||
adt_async_destructor,
|
||||
region_scope_tree,
|
||||
collect_return_position_impl_trait_in_trait_tys,
|
||||
compare_impl_const: compare_impl_item::compare_impl_const_raw,
|
||||
|
|
@ -124,6 +125,10 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor>
|
|||
tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl)
|
||||
}
|
||||
|
||||
fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
|
||||
tcx.calculate_async_dtor(def_id.to_def_id(), dropck::check_drop_impl)
|
||||
}
|
||||
|
||||
/// Given a `DefId` for an opaque type in return position, find its parent item's return
|
||||
/// expressions.
|
||||
fn get_owner_return_paths(
|
||||
|
|
@ -436,7 +441,9 @@ fn fn_sig_suggestion<'tcx>(
|
|||
output = if let ty::Alias(_, alias_ty) = *output.kind() {
|
||||
tcx.explicit_item_super_predicates(alias_ty.def_id)
|
||||
.iter_instantiated_copied(tcx, alias_ty.args)
|
||||
.find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
|
||||
.find_map(|(bound, _)| {
|
||||
bound.as_projection_clause()?.no_bound_vars()?.term.as_type()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
ident.span,
|
||||
|
|
@ -594,7 +601,7 @@ pub fn check_function_signature<'tcx>(
|
|||
let param_env = ty::ParamEnv::empty();
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
let actual_sig = tcx.fn_sig(fn_id).instantiate_identity();
|
||||
|
||||
|
|
|
|||
|
|
@ -818,7 +818,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
|
|||
resolve_block(self, b);
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
|
||||
fn visit_body(&mut self, body: &hir::Body<'tcx>) {
|
||||
let body_id = body.id();
|
||||
let owner_id = self.tcx.hir().body_owner_def_id(body_id);
|
||||
|
||||
|
|
@ -896,7 +896,7 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
|
|||
return tcx.region_scope_tree(typeck_root_def_id);
|
||||
}
|
||||
|
||||
let scope_tree = if let Some(body_id) = tcx.hir().maybe_body_owned_by(def_id.expect_local()) {
|
||||
let scope_tree = if let Some(body) = tcx.hir().maybe_body_owned_by(def_id.expect_local()) {
|
||||
let mut visitor = RegionResolutionVisitor {
|
||||
tcx,
|
||||
scope_tree: ScopeTree::default(),
|
||||
|
|
@ -907,9 +907,8 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
|
|||
fixup_scopes: vec![],
|
||||
};
|
||||
|
||||
let body = tcx.hir().body(body_id);
|
||||
visitor.scope_tree.root_body = Some(body.value.hir_id);
|
||||
visitor.visit_body(body);
|
||||
visitor.visit_body(&body);
|
||||
visitor.scope_tree
|
||||
} else {
|
||||
ScopeTree::default()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ use rustc_trait_selection::traits::misc::{
|
|||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
|
||||
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
|
||||
};
|
||||
use rustc_type_ir::TypeFlags;
|
||||
|
||||
|
|
@ -45,13 +45,13 @@ use std::cell::LazyCell;
|
|||
use std::ops::{ControlFlow, Deref};
|
||||
|
||||
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
|
||||
pub(super) ocx: ObligationCtxt<'a, 'tcx>,
|
||||
pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
|
||||
span: Span,
|
||||
body_def_id: LocalDefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> {
|
||||
type Target = ObligationCtxt<'a, 'tcx>;
|
||||
type Target = ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.ocx
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ where
|
|||
{
|
||||
let param_env = tcx.param_env(body_def_id);
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
|
||||
|
||||
|
|
@ -881,7 +881,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
|
|||
_ => {}
|
||||
}
|
||||
if !trait_should_be_self.is_empty() {
|
||||
if tcx.check_is_object_safe(trait_def_id) {
|
||||
if tcx.is_object_safe(trait_def_id) {
|
||||
return;
|
||||
}
|
||||
let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
|||
.join(", "),
|
||||
}));
|
||||
} else {
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
for field in coerced_fields {
|
||||
ocx.register_obligation(Obligation::new(
|
||||
tcx,
|
||||
|
|
@ -480,7 +480,7 @@ pub fn coerce_unsized_info<'tcx>(
|
|||
};
|
||||
|
||||
// Register an obligation for `A: Trait<B>`.
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
let cause = traits::ObligationCause::misc(span, impl_did);
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
|
|
@ -554,7 +554,7 @@ fn infringing_fields_error(
|
|||
if let ty::Param(_) = ty.kind() {
|
||||
bounds.push((
|
||||
format!("{ty}"),
|
||||
trait_ref.print_only_trait_path().to_string(),
|
||||
trait_ref.print_trait_sugared().to_string(),
|
||||
Some(trait_ref.def_id),
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use rustc_middle::query::Providers;
|
|||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{sym, ErrorGuaranteed};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
mod builtin;
|
||||
mod inherent_impls;
|
||||
|
|
@ -192,14 +191,14 @@ fn check_object_overlap<'tcx>(
|
|||
});
|
||||
|
||||
for component_def_id in component_def_ids {
|
||||
if !tcx.check_is_object_safe(component_def_id) {
|
||||
if !tcx.is_object_safe(component_def_id) {
|
||||
// Without the 'object_safe_for_dispatch' feature this is an error
|
||||
// which will be reported by wfcheck. Ignore it here.
|
||||
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
|
||||
// With the feature enabled, the trait is not implemented automatically,
|
||||
// so this is valid.
|
||||
} else {
|
||||
let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id);
|
||||
let mut supertrait_def_ids = tcx.supertrait_def_ids(component_def_id);
|
||||
if supertrait_def_ids.any(|d| d == trait_def_id) {
|
||||
let span = tcx.def_span(impl_def_id);
|
||||
return Err(struct_span_code_err!(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ use rustc_middle::{bug, span_bug};
|
|||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams};
|
||||
use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode};
|
||||
use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt};
|
||||
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub(crate) fn orphan_check_impl(
|
||||
|
|
@ -317,12 +316,12 @@ fn orphan_check<'tcx>(
|
|||
}
|
||||
|
||||
let ty = if infcx.next_trait_solver() {
|
||||
let mut fulfill_cx = <dyn traits::TraitEngine<'_>>::new(&infcx);
|
||||
infcx
|
||||
.at(&cause, ty::ParamEnv::empty())
|
||||
.structurally_normalize(ty, &mut *fulfill_cx)
|
||||
.map(|ty| infcx.resolve_vars_if_possible(ty))
|
||||
.unwrap_or(ty)
|
||||
ocx.structurally_normalize(
|
||||
&cause,
|
||||
ty::ParamEnv::empty(),
|
||||
infcx.resolve_vars_if_possible(ty),
|
||||
)
|
||||
.unwrap_or(ty)
|
||||
} else {
|
||||
ty
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1468,12 +1468,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
depth: usize,
|
||||
generic_args: &'tcx hir::GenericArgs<'tcx>,
|
||||
) {
|
||||
if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
|
||||
self.visit_fn_like_elision(
|
||||
generic_args.inputs(),
|
||||
Some(generic_args.bindings[0].ty()),
|
||||
false,
|
||||
);
|
||||
if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
|
||||
self.visit_fn_like_elision(inputs, Some(output), false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1608,8 +1604,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Hack: when resolving the type `XX` in binding like `dyn
|
||||
// Foo<'b, Item = XX>`, the current object-lifetime default
|
||||
// Hack: When resolving the type `XX` in an assoc ty binding like
|
||||
// `dyn Foo<'b, Item = XX>`, the current object-lifetime default
|
||||
// would be to examine the trait `Foo` to check whether it has
|
||||
// a lifetime bound declared on `Item`. e.g., if `Foo` is
|
||||
// declared like so, then the default object lifetime bound in
|
||||
|
|
@ -1637,7 +1633,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
|
||||
// Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
|
||||
// in the trait ref `YY<...>` in `Item: YY<...>`.
|
||||
for binding in generic_args.bindings {
|
||||
for constraint in generic_args.constraints {
|
||||
let scope = Scope::ObjectLifetimeDefault {
|
||||
lifetime: if has_lifetime_parameter {
|
||||
None
|
||||
|
|
@ -1646,7 +1642,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
},
|
||||
s: self.scope,
|
||||
};
|
||||
// If the binding is parenthesized, then this must be `feature(return_type_notation)`.
|
||||
// If the args are parenthesized, then this must be `feature(return_type_notation)`.
|
||||
// In that case, introduce a binder over all of the function's early and late bound vars.
|
||||
//
|
||||
// For example, given
|
||||
|
|
@ -1659,13 +1655,14 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
// `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
|
||||
// this is going to expand to something like:
|
||||
// `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
|
||||
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
|
||||
if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
|
||||
{
|
||||
let bound_vars = if let Some(type_def_id) = type_def_id
|
||||
&& self.tcx.def_kind(type_def_id) == DefKind::Trait
|
||||
&& let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars(
|
||||
self.tcx,
|
||||
type_def_id,
|
||||
binding.ident,
|
||||
constraint.ident,
|
||||
ty::AssocKind::Fn,
|
||||
) {
|
||||
bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).own_params.iter().map(
|
||||
|
|
@ -1686,22 +1683,22 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
} else {
|
||||
self.tcx
|
||||
.dcx()
|
||||
.span_delayed_bug(binding.ident.span, "bad return type notation here");
|
||||
.span_delayed_bug(constraint.ident.span, "bad return type notation here");
|
||||
vec![]
|
||||
};
|
||||
self.with(scope, |this| {
|
||||
let scope = Scope::Supertrait { bound_vars, s: this.scope };
|
||||
this.with(scope, |this| {
|
||||
let (bound_vars, _) = this.poly_trait_ref_binder_info();
|
||||
this.record_late_bound_vars(binding.hir_id, bound_vars);
|
||||
this.visit_assoc_type_binding(binding)
|
||||
this.record_late_bound_vars(constraint.hir_id, bound_vars);
|
||||
this.visit_assoc_item_constraint(constraint)
|
||||
});
|
||||
});
|
||||
} else if let Some(type_def_id) = type_def_id {
|
||||
let bound_vars = BoundVarContext::supertrait_hrtb_vars(
|
||||
self.tcx,
|
||||
type_def_id,
|
||||
binding.ident,
|
||||
constraint.ident,
|
||||
ty::AssocKind::Type,
|
||||
)
|
||||
.map(|(bound_vars, _)| bound_vars);
|
||||
|
|
@ -1710,10 +1707,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
bound_vars: bound_vars.unwrap_or_default(),
|
||||
s: this.scope,
|
||||
};
|
||||
this.with(scope, |this| this.visit_assoc_type_binding(binding));
|
||||
this.with(scope, |this| this.visit_assoc_item_constraint(constraint));
|
||||
});
|
||||
} else {
|
||||
self.with(scope, |this| this.visit_assoc_type_binding(binding));
|
||||
self.with(scope, |this| this.visit_assoc_item_constraint(constraint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,9 +220,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
.position(|arg| arg.hir_id() == hir_id)
|
||||
.map(|index| (index, seg))
|
||||
.or_else(|| {
|
||||
args.bindings
|
||||
args.constraints
|
||||
.iter()
|
||||
.filter_map(TypeBinding::opt_const)
|
||||
.copied()
|
||||
.filter_map(AssocItemConstraint::ct)
|
||||
.position(|ct| ct.hir_id == hir_id)
|
||||
.map(|idx| (idx, seg))
|
||||
})
|
||||
|
|
@ -501,7 +502,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
|
|||
bug!("unexpected sort of node in type_of(): {:?}", x);
|
||||
}
|
||||
};
|
||||
if let Err(e) = icx.check_tainted_by_errors() {
|
||||
if let Err(e) = icx.check_tainted_by_errors()
|
||||
&& !output.references_error()
|
||||
{
|
||||
ty::EarlyBinder::bind(Ty::new_error(tcx, e))
|
||||
} else {
|
||||
ty::EarlyBinder::bind(output)
|
||||
|
|
|
|||
|
|
@ -290,8 +290,8 @@ pub struct AmbiguousLifetimeBound {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_assoc_type_binding_not_allowed, code = E0229)]
|
||||
pub struct AssocTypeBindingNotAllowed {
|
||||
#[diag(hir_analysis_assoc_item_constraints_not_allowed_here, code = E0229)]
|
||||
pub struct AssocItemConstraintsNotAllowedHere {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
|
|
|
|||
|
|
@ -230,32 +230,34 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
bounds
|
||||
}
|
||||
|
||||
/// Lower an associated item binding from HIR into `bounds`.
|
||||
/// Lower an associated item constraint from the HIR into `bounds`.
|
||||
///
|
||||
/// ### A Note on Binders
|
||||
///
|
||||
/// Given something like `T: for<'a> Iterator<Item = &'a u32>`,
|
||||
/// the `trait_ref` here will be `for<'a> T: Iterator`.
|
||||
/// The `binding` data however is from *inside* the binder
|
||||
/// The `constraint` data however is from *inside* the binder
|
||||
/// (e.g., `&'a u32`) and hence may reference bound regions.
|
||||
#[instrument(level = "debug", skip(self, bounds, dup_bindings, path_span))]
|
||||
pub(super) fn lower_assoc_item_binding(
|
||||
#[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
|
||||
pub(super) fn lower_assoc_item_constraint(
|
||||
&self,
|
||||
hir_ref_id: hir::HirId,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
binding: &hir::TypeBinding<'tcx>,
|
||||
constraint: &hir::AssocItemConstraint<'tcx>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
dup_bindings: &mut FxIndexMap<DefId, Span>,
|
||||
duplicates: &mut FxIndexMap<DefId, Span>,
|
||||
path_span: Span,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let assoc_kind = if binding.gen_args.parenthesized
|
||||
let assoc_kind = if constraint.gen_args.parenthesized
|
||||
== hir::GenericArgsParentheses::ReturnTypeNotation
|
||||
{
|
||||
ty::AssocKind::Fn
|
||||
} else if let hir::TypeBindingKind::Equality { term: hir::Term::Const(_) } = binding.kind {
|
||||
} else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
|
||||
constraint.kind
|
||||
{
|
||||
ty::AssocKind::Const
|
||||
} else {
|
||||
ty::AssocKind::Type
|
||||
|
|
@ -272,7 +274,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let candidate = if self.probe_trait_that_defines_assoc_item(
|
||||
trait_ref.def_id(),
|
||||
assoc_kind,
|
||||
binding.ident,
|
||||
constraint.ident,
|
||||
) {
|
||||
// Simple case: The assoc item is defined in the current trait.
|
||||
trait_ref
|
||||
|
|
@ -284,14 +286,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
trait_ref.skip_binder().print_only_trait_name(),
|
||||
None,
|
||||
assoc_kind,
|
||||
binding.ident,
|
||||
constraint.ident,
|
||||
path_span,
|
||||
Some(binding),
|
||||
Some(constraint),
|
||||
)?
|
||||
};
|
||||
|
||||
let (assoc_ident, def_scope) =
|
||||
tcx.adjust_ident_and_get_scope(binding.ident, candidate.def_id(), hir_ref_id);
|
||||
tcx.adjust_ident_and_get_scope(constraint.ident, candidate.def_id(), hir_ref_id);
|
||||
|
||||
// We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()`
|
||||
// instead of calling `filter_by_name_and_kind` which would needlessly normalize the
|
||||
|
|
@ -306,26 +308,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let reported = tcx
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
binding.span,
|
||||
format!("{} `{}` is private", assoc_item.kind, binding.ident),
|
||||
constraint.span,
|
||||
format!("{} `{}` is private", assoc_item.kind, constraint.ident),
|
||||
)
|
||||
.with_span_label(binding.span, format!("private {}", assoc_item.kind))
|
||||
.with_span_label(constraint.span, format!("private {}", assoc_item.kind))
|
||||
.emit();
|
||||
self.set_tainted_by_errors(reported);
|
||||
}
|
||||
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
|
||||
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), constraint.span, None);
|
||||
|
||||
dup_bindings
|
||||
duplicates
|
||||
.entry(assoc_item.def_id)
|
||||
.and_modify(|prev_span| {
|
||||
tcx.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
|
||||
span: binding.span,
|
||||
span: constraint.span,
|
||||
prev_span: *prev_span,
|
||||
item_name: binding.ident,
|
||||
item_name: constraint.ident,
|
||||
def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
|
||||
});
|
||||
})
|
||||
.or_insert(binding.span);
|
||||
.or_insert(constraint.span);
|
||||
|
||||
let projection_term = if let ty::AssocKind::Fn = assoc_kind {
|
||||
let mut emitted_bad_param_err = None;
|
||||
|
|
@ -384,7 +386,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
alias_ty.into()
|
||||
} else {
|
||||
return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
|
||||
span: binding.span,
|
||||
span: constraint.span,
|
||||
ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output),
|
||||
fn_span: tcx.hir().span_if_local(assoc_item.def_id),
|
||||
note: (),
|
||||
|
|
@ -398,19 +400,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
|
||||
let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
|
||||
|
||||
let bound_vars = tcx.late_bound_vars(binding.hir_id);
|
||||
let bound_vars = tcx.late_bound_vars(constraint.hir_id);
|
||||
ty::Binder::bind_with_vars(instantiation_output, bound_vars)
|
||||
} else {
|
||||
// Create the generic arguments for the associated type or constant by joining the
|
||||
// parent arguments (the arguments of the trait) and the own arguments (the ones of
|
||||
// the associated item itself) and construct an alias type using them.
|
||||
let alias_ty = candidate.map_bound(|trait_ref| {
|
||||
let ident = Ident::new(assoc_item.name, binding.ident.span);
|
||||
let ident = Ident::new(assoc_item.name, constraint.ident.span);
|
||||
let item_segment = hir::PathSegment {
|
||||
ident,
|
||||
hir_id: binding.hir_id,
|
||||
hir_id: constraint.hir_id,
|
||||
res: Res::Err,
|
||||
args: Some(binding.gen_args),
|
||||
args: Some(constraint.gen_args),
|
||||
infer_args: false,
|
||||
};
|
||||
|
||||
|
|
@ -426,26 +428,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
});
|
||||
|
||||
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
|
||||
if let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } =
|
||||
binding.kind
|
||||
if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(anon_const) } =
|
||||
constraint.kind
|
||||
{
|
||||
let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
|
||||
let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, binding.hir_id);
|
||||
let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, constraint.hir_id);
|
||||
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
|
||||
alias_ty
|
||||
};
|
||||
|
||||
match binding.kind {
|
||||
hir::TypeBindingKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => {
|
||||
match constraint.kind {
|
||||
hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => {
|
||||
return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
|
||||
span: binding.span,
|
||||
span: constraint.span,
|
||||
}));
|
||||
}
|
||||
// Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator<Item = u32>`
|
||||
// to a projection predicate: `<T as Iterator>::Item = u32`.
|
||||
hir::TypeBindingKind::Equality { term } => {
|
||||
hir::AssocItemConstraintKind::Equality { term } => {
|
||||
let term = match term {
|
||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||
hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(),
|
||||
|
|
@ -469,18 +471,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
|
||||
// ---- ---- ^^^^^^^
|
||||
// NOTE(associated_const_equality): This error should be impossible to trigger
|
||||
// with associated const equality bounds.
|
||||
// with associated const equality constraints.
|
||||
self.validate_late_bound_regions(
|
||||
late_bound_in_projection_ty,
|
||||
late_bound_in_term,
|
||||
|br_name| {
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
binding.span,
|
||||
constraint.span,
|
||||
E0582,
|
||||
"binding for associated type `{}` references {}, \
|
||||
which does not appear in the trait input types",
|
||||
binding.ident,
|
||||
which does not appear in the trait input types",
|
||||
constraint.ident,
|
||||
br_name
|
||||
)
|
||||
},
|
||||
|
|
@ -492,12 +494,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
projection_term,
|
||||
term,
|
||||
}),
|
||||
binding.span,
|
||||
constraint.span,
|
||||
);
|
||||
}
|
||||
// Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
|
||||
// to a bound involving a projection: `<T as Iterator>::Item: Debug`.
|
||||
hir::TypeBindingKind::Constraint { bounds: hir_bounds } => {
|
||||
hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
|
||||
// NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into
|
||||
// a trait predicate, since we only want to add predicates for the `Self` type.
|
||||
if !only_self_bounds.0 {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::errors::{
|
||||
self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
|
||||
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
|
||||
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
|
|
@ -15,7 +15,6 @@ use rustc_errors::{
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_infer::traits::FulfillmentError;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Key;
|
||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
||||
|
|
@ -28,6 +27,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
|
|||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::BytePos;
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
use rustc_trait_selection::traits::FulfillmentError;
|
||||
use rustc_trait_selection::traits::{
|
||||
object_safety_violations_for_assoc_item, TraitAliasExpansionInfo,
|
||||
};
|
||||
|
|
@ -121,7 +121,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
assoc_kind: ty::AssocKind,
|
||||
assoc_name: Ident,
|
||||
span: Span,
|
||||
binding: Option<&hir::TypeBinding<'tcx>>,
|
||||
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
|
||||
) -> ErrorGuaranteed
|
||||
where
|
||||
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||
|
|
@ -135,7 +135,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id()))
|
||||
}) {
|
||||
return self.complain_about_assoc_kind_mismatch(
|
||||
assoc_item, assoc_kind, assoc_name, span, binding,
|
||||
assoc_item, assoc_kind, assoc_name, span, constraint,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -300,18 +300,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
assoc_kind: ty::AssocKind,
|
||||
ident: Ident,
|
||||
span: Span,
|
||||
binding: Option<&hir::TypeBinding<'tcx>>,
|
||||
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
|
||||
) -> ErrorGuaranteed {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind
|
||||
&& let Some(binding) = binding
|
||||
&& let hir::TypeBindingKind::Constraint { .. } = binding.kind
|
||||
&& let Some(constraint) = constraint
|
||||
&& let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
|
||||
{
|
||||
let lo = if binding.gen_args.span_ext.is_dummy() {
|
||||
let lo = if constraint.gen_args.span_ext.is_dummy() {
|
||||
ident.span
|
||||
} else {
|
||||
binding.gen_args.span_ext
|
||||
constraint.gen_args.span_ext
|
||||
};
|
||||
Some(lo.between(span.shrink_to_hi()))
|
||||
} else {
|
||||
|
|
@ -319,8 +319,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
};
|
||||
|
||||
// FIXME(associated_const_equality): This has quite a few false positives and negatives.
|
||||
let wrap_in_braces_sugg = if let Some(binding) = binding
|
||||
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(hir_ty) } = binding.kind
|
||||
let wrap_in_braces_sugg = if let Some(constraint) = constraint
|
||||
&& let Some(hir_ty) = constraint.ty()
|
||||
&& let ty = self.lower_ty(hir_ty)
|
||||
&& (ty.is_enum() || ty.references_error())
|
||||
&& tcx.features().associated_const_equality
|
||||
|
|
@ -333,10 +333,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
None
|
||||
};
|
||||
|
||||
// For equality bounds, we want to blame the term (RHS) instead of the item (LHS) since
|
||||
// For equality constraints, we want to blame the term (RHS) instead of the item (LHS) since
|
||||
// one can argue that that's more “intuitive” to the user.
|
||||
let (span, expected_because_label, expected, got) = if let Some(binding) = binding
|
||||
&& let hir::TypeBindingKind::Equality { term } = binding.kind
|
||||
let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint
|
||||
&& let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
|
||||
{
|
||||
let span = match term {
|
||||
hir::Term::Ty(ty) => ty.span,
|
||||
|
|
@ -702,7 +702,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
pub(crate) fn complain_about_missing_assoc_tys(
|
||||
&self,
|
||||
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
|
||||
potential_assoc_types: Vec<Span>,
|
||||
potential_assoc_types: Vec<usize>,
|
||||
trait_bounds: &[hir::PolyTraitRef<'_>],
|
||||
) {
|
||||
if associated_types.values().all(|v| v.is_empty()) {
|
||||
|
|
@ -791,8 +791,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let path = poly_trait_ref.trait_ref.path.segments.last()?;
|
||||
let args = path.args?;
|
||||
|
||||
Some(args.bindings.iter().filter_map(|binding| {
|
||||
let ident = binding.ident;
|
||||
Some(args.constraints.iter().filter_map(|constraint| {
|
||||
let ident = constraint.ident;
|
||||
let trait_def = path.res.def_id();
|
||||
let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind(
|
||||
tcx,
|
||||
|
|
@ -1192,14 +1192,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
}
|
||||
|
||||
/// Emits an error regarding forbidden type binding associations
|
||||
pub fn prohibit_assoc_item_binding(
|
||||
/// Emit an error for the given associated item constraint.
|
||||
pub fn prohibit_assoc_item_constraint(
|
||||
tcx: TyCtxt<'_>,
|
||||
binding: &hir::TypeBinding<'_>,
|
||||
constraint: &hir::AssocItemConstraint<'_>,
|
||||
segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
|
||||
) -> ErrorGuaranteed {
|
||||
let mut err = tcx.dcx().create_err(AssocTypeBindingNotAllowed {
|
||||
span: binding.span,
|
||||
let mut err = tcx.dcx().create_err(AssocItemConstraintsNotAllowedHere {
|
||||
span: constraint.span,
|
||||
fn_trait_expansion: if let Some((_, segment, span)) = segment
|
||||
&& segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
|
||||
{
|
||||
|
|
@ -1217,13 +1217,12 @@ pub fn prohibit_assoc_item_binding(
|
|||
// otherwise suggest the removal of the binding.
|
||||
if let Some((def_id, segment, _)) = segment
|
||||
&& segment.args().parenthesized == hir::GenericArgsParentheses::No
|
||||
&& let hir::TypeBindingKind::Equality { term } = binding.kind
|
||||
&& let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
|
||||
{
|
||||
// Suggests removal of the offending binding
|
||||
let suggest_removal = |e: &mut Diag<'_>| {
|
||||
let bindings = segment.args().bindings;
|
||||
let constraints = segment.args().constraints;
|
||||
let args = segment.args().args;
|
||||
let binding_span = binding.span;
|
||||
|
||||
// Compute the span to remove based on the position
|
||||
// of the binding. We do that as follows:
|
||||
|
|
@ -1236,26 +1235,21 @@ pub fn prohibit_assoc_item_binding(
|
|||
// the start of the next span or will simply be the
|
||||
// span encomassing everything within the generics brackets
|
||||
|
||||
let Some(binding_index) = bindings.iter().position(|b| b.hir_id == binding.hir_id)
|
||||
else {
|
||||
let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else {
|
||||
bug!("a type binding exists but its HIR ID not found in generics");
|
||||
};
|
||||
|
||||
let preceding_span = if binding_index > 0 {
|
||||
Some(bindings[binding_index - 1].span)
|
||||
let preceding_span = if index > 0 {
|
||||
Some(constraints[index - 1].span)
|
||||
} else {
|
||||
args.last().map(|a| a.span())
|
||||
};
|
||||
|
||||
let next_span = if binding_index < bindings.len() - 1 {
|
||||
Some(bindings[binding_index + 1].span)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let next_span = constraints.get(index + 1).map(|constraint| constraint.span);
|
||||
|
||||
let removal_span = match (preceding_span, next_span) {
|
||||
(Some(prec), _) => binding_span.with_lo(prec.hi()),
|
||||
(None, Some(next)) => binding_span.with_hi(next.lo()),
|
||||
(Some(prec), _) => constraint.span.with_lo(prec.hi()),
|
||||
(None, Some(next)) => constraint.span.with_hi(next.lo()),
|
||||
(None, None) => {
|
||||
let Some(generics_span) = segment.args().span_ext() else {
|
||||
bug!("a type binding exists but generic span is empty");
|
||||
|
|
@ -1269,7 +1263,7 @@ pub fn prohibit_assoc_item_binding(
|
|||
if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
|
||||
e.span_suggestion_verbose(
|
||||
removal_span,
|
||||
"consider removing this type binding",
|
||||
"consider removing this associated item binding",
|
||||
suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
@ -1281,7 +1275,7 @@ pub fn prohibit_assoc_item_binding(
|
|||
let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
|
||||
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
|
||||
e.span_suggestion_verbose(
|
||||
binding.span,
|
||||
constraint.span,
|
||||
format!("to use `{snippet}` as a generic argument specify it directly"),
|
||||
snippet,
|
||||
Applicability::MaybeIncorrect,
|
||||
|
|
@ -1289,11 +1283,11 @@ pub fn prohibit_assoc_item_binding(
|
|||
}
|
||||
};
|
||||
|
||||
// Check if the type has a generic param with the
|
||||
// same name as the assoc type name in type binding
|
||||
// Check if the type has a generic param with the same name
|
||||
// as the assoc type name in the associated item binding.
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let matching_param =
|
||||
generics.own_params.iter().find(|p| p.name.as_str() == binding.ident.as_str());
|
||||
generics.own_params.iter().find(|p| p.name.as_str() == constraint.ident.as_str());
|
||||
|
||||
// Now emit the appropriate suggestion
|
||||
if let Some(matching_param) = matching_param {
|
||||
|
|
@ -1322,8 +1316,7 @@ pub(crate) fn fn_trait_to_string(
|
|||
) -> String {
|
||||
let args = trait_segment
|
||||
.args
|
||||
.as_ref()
|
||||
.and_then(|args| args.args.get(0))
|
||||
.and_then(|args| args.args.first())
|
||||
.and_then(|arg| match arg {
|
||||
hir::GenericArg::Type(ty) => match ty.kind {
|
||||
hir::TyKind::Tup(t) => t
|
||||
|
|
@ -1334,7 +1327,7 @@ pub(crate) fn fn_trait_to_string(
|
|||
_ => tcx.sess.source_map().span_to_snippet(ty.span),
|
||||
}
|
||||
.map(|s| {
|
||||
// `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma
|
||||
// `is_empty()` checks to see if the type is the unit tuple, if so we don't want a comma
|
||||
if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") }
|
||||
})
|
||||
.ok(),
|
||||
|
|
@ -1344,20 +1337,17 @@ pub(crate) fn fn_trait_to_string(
|
|||
|
||||
let ret = trait_segment
|
||||
.args()
|
||||
.bindings
|
||||
.constraints
|
||||
.iter()
|
||||
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
|
||||
(true, hir::TypeBindingKind::Equality { term }) => {
|
||||
let span = match term {
|
||||
hir::Term::Ty(ty) => ty.span,
|
||||
hir::Term::Const(c) => tcx.hir().span(c.hir_id),
|
||||
};
|
||||
|
||||
(span != tcx.hir().span(trait_segment.hir_id))
|
||||
.then_some(tcx.sess.source_map().span_to_snippet(span).ok())
|
||||
.flatten()
|
||||
.find_map(|c| {
|
||||
if c.ident.name == sym::Output
|
||||
&& let Some(ty) = c.ty()
|
||||
&& ty.span != tcx.hir().span(trait_segment.hir_id)
|
||||
{
|
||||
tcx.sess.source_map().span_to_snippet(ty.span).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| "()".to_string());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::IsMethodCall;
|
||||
use crate::hir_ty_lowering::{
|
||||
errors::prohibit_assoc_item_binding, ExplicitLateBound, GenericArgCountMismatch,
|
||||
errors::prohibit_assoc_item_constraint, ExplicitLateBound, GenericArgCountMismatch,
|
||||
GenericArgCountResult, GenericArgPosition, GenericArgsLowerer,
|
||||
};
|
||||
use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs};
|
||||
|
|
@ -214,10 +214,11 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
if let Some(¶m) = params.peek() {
|
||||
if param.index == 0 {
|
||||
if let GenericParamDefKind::Type { .. } = param.kind {
|
||||
assert_eq!(&args[..], &[]);
|
||||
args.push(
|
||||
self_ty
|
||||
.map(|ty| ty.into())
|
||||
.unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
|
||||
.unwrap_or_else(|| ctx.inferred_kind(&args, param, true)),
|
||||
);
|
||||
params.next();
|
||||
}
|
||||
|
|
@ -267,7 +268,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
// Since this is a const impl, we need to insert a host arg at the end of
|
||||
// `PartialEq`'s generics, but this errors since `Rhs` isn't specified.
|
||||
// To work around this, we infer all arguments until we reach the host param.
|
||||
args.push(ctx.inferred_kind(Some(&args), param, infer_args));
|
||||
args.push(ctx.inferred_kind(&args, param, infer_args));
|
||||
params.next();
|
||||
}
|
||||
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
|
||||
|
|
@ -281,7 +282,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
GenericParamDefKind::Const { .. },
|
||||
_,
|
||||
) => {
|
||||
args.push(ctx.provided_kind(param, arg));
|
||||
args.push(ctx.provided_kind(&args, param, arg));
|
||||
args_iter.next();
|
||||
params.next();
|
||||
}
|
||||
|
|
@ -292,7 +293,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
) => {
|
||||
// We expected a lifetime argument, but got a type or const
|
||||
// argument. That means we're inferring the lifetimes.
|
||||
args.push(ctx.inferred_kind(None, param, infer_args));
|
||||
args.push(ctx.inferred_kind(&args, param, infer_args));
|
||||
force_infer_lt = Some((arg, param));
|
||||
params.next();
|
||||
}
|
||||
|
|
@ -388,7 +389,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
(None, Some(¶m)) => {
|
||||
// If there are fewer arguments than parameters, it means
|
||||
// we're inferring the remaining arguments.
|
||||
args.push(ctx.inferred_kind(Some(&args), param, infer_args));
|
||||
args.push(ctx.inferred_kind(&args, param, infer_args));
|
||||
params.next();
|
||||
}
|
||||
|
||||
|
|
@ -452,9 +453,9 @@ pub(crate) fn check_generic_arg_count(
|
|||
(gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params();
|
||||
|
||||
if gen_pos != GenericArgPosition::Type
|
||||
&& let Some(b) = gen_args.bindings.first()
|
||||
&& let Some(c) = gen_args.constraints.first()
|
||||
{
|
||||
prohibit_assoc_item_binding(tcx, b, None);
|
||||
prohibit_assoc_item_constraint(tcx, c, None);
|
||||
}
|
||||
|
||||
let explicit_late_bound =
|
||||
|
|
@ -474,16 +475,9 @@ pub(crate) fn check_generic_arg_count(
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
if provided_args > max_expected_args {
|
||||
invalid_args.extend(
|
||||
gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()),
|
||||
);
|
||||
};
|
||||
invalid_args.extend(min_expected_args..provided_args);
|
||||
|
||||
let gen_args_info = if provided_args > min_expected_args {
|
||||
invalid_args.extend(
|
||||
gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()),
|
||||
);
|
||||
let num_redundant_args = provided_args - min_expected_args;
|
||||
GenericArgsInfo::ExcessLifetimes { num_redundant_args }
|
||||
} else {
|
||||
|
|
@ -538,11 +532,7 @@ pub(crate) fn check_generic_arg_count(
|
|||
let num_default_params = expected_max - expected_min;
|
||||
|
||||
let gen_args_info = if provided > expected_max {
|
||||
invalid_args.extend(
|
||||
gen_args.args[args_offset + expected_max..args_offset + provided]
|
||||
.iter()
|
||||
.map(|arg| arg.span()),
|
||||
);
|
||||
invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
|
||||
let num_redundant_args = provided - expected_max;
|
||||
|
||||
// Provide extra note if synthetic arguments like `impl Trait` are specified.
|
||||
|
|
@ -566,17 +556,19 @@ pub(crate) fn check_generic_arg_count(
|
|||
|
||||
debug!(?gen_args_info);
|
||||
|
||||
let reported = WrongNumberOfGenericArgs::new(
|
||||
tcx,
|
||||
gen_args_info,
|
||||
seg,
|
||||
gen_params,
|
||||
params_offset,
|
||||
gen_args,
|
||||
def_id,
|
||||
)
|
||||
.diagnostic()
|
||||
.emit_unless(gen_args.has_err());
|
||||
let reported = gen_args.has_err().unwrap_or_else(|| {
|
||||
WrongNumberOfGenericArgs::new(
|
||||
tcx,
|
||||
gen_args_info,
|
||||
seg,
|
||||
gen_params,
|
||||
params_offset,
|
||||
gen_args,
|
||||
def_id,
|
||||
)
|
||||
.diagnostic()
|
||||
.emit()
|
||||
});
|
||||
|
||||
Err(reported)
|
||||
};
|
||||
|
|
@ -608,7 +600,7 @@ pub(crate) fn check_generic_arg_count(
|
|||
explicit_late_bound,
|
||||
correct: lifetimes_correct
|
||||
.and(args_correct)
|
||||
.map_err(|reported| GenericArgCountMismatch { reported: Some(reported), invalid_args }),
|
||||
.map_err(|reported| GenericArgCountMismatch { reported, invalid_args }),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// For recursive traits, don't downgrade the error. (#119652)
|
||||
is_downgradable = false;
|
||||
}
|
||||
tcx.check_is_object_safe(id)
|
||||
tcx.is_object_safe(id)
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
|
|
@ -268,8 +268,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) {
|
||||
let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id);
|
||||
|
||||
if let Some((_, hir::Node::TypeBinding(binding))) = parents.next()
|
||||
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(obj_ty) } = binding.kind
|
||||
if let Some((_, hir::Node::AssocItemConstraint(constraint))) = parents.next()
|
||||
&& let Some(obj_ty) = constraint.ty()
|
||||
{
|
||||
if let Some((_, hir::Node::TraitRef(..))) = parents.next()
|
||||
&& let Some((_, hir::Node::Ty(ty))) = parents.next()
|
||||
|
|
@ -279,10 +279,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
return;
|
||||
}
|
||||
|
||||
let lo = if binding.gen_args.span_ext.is_dummy() {
|
||||
binding.ident.span
|
||||
let lo = if constraint.gen_args.span_ext.is_dummy() {
|
||||
constraint.ident.span
|
||||
} else {
|
||||
binding.gen_args.span_ext
|
||||
constraint.gen_args.span_ext
|
||||
};
|
||||
let hi = obj_ty.span;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ mod object_safety;
|
|||
use crate::bounds::Bounds;
|
||||
use crate::collect::HirPlaceholderCollector;
|
||||
use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
|
||||
use crate::hir_ty_lowering::errors::{prohibit_assoc_item_binding, GenericsArgsErrExtend};
|
||||
use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
|
||||
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
|
||||
use crate::middle::resolve_bound_vars as rbv;
|
||||
use crate::require_c_abi_if_c_variadic;
|
||||
|
|
@ -215,12 +215,11 @@ pub(crate) enum GenericArgPosition {
|
|||
|
||||
/// A marker denoting that the generic arguments that were
|
||||
/// provided did not match the respective generic parameters.
|
||||
#[derive(Clone, Default, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GenericArgCountMismatch {
|
||||
/// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
|
||||
pub reported: Option<ErrorGuaranteed>,
|
||||
/// A list of spans of arguments provided that were not valid.
|
||||
pub invalid_args: Vec<Span>,
|
||||
pub reported: ErrorGuaranteed,
|
||||
/// A list of indices of arguments provided that were not valid.
|
||||
pub invalid_args: Vec<usize>,
|
||||
}
|
||||
|
||||
/// Decorates the result of a generic argument count mismatch
|
||||
|
|
@ -240,13 +239,14 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
|
|||
|
||||
fn provided_kind(
|
||||
&mut self,
|
||||
preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
arg: &GenericArg<'tcx>,
|
||||
) -> ty::GenericArg<'tcx>;
|
||||
|
||||
fn inferred_kind(
|
||||
&mut self,
|
||||
args: Option<&[ty::GenericArg<'tcx>]>,
|
||||
preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
infer_args: bool,
|
||||
) -> ty::GenericArg<'tcx>;
|
||||
|
|
@ -324,8 +324,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
None,
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
prohibit_assoc_item_binding(self.tcx(), b, Some((def_id, item_segment, span)));
|
||||
if let Some(c) = item_segment.args().constraints.first() {
|
||||
prohibit_assoc_item_constraint(self.tcx(), c, Some((def_id, item_segment, span)));
|
||||
}
|
||||
args
|
||||
}
|
||||
|
|
@ -335,7 +335,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
/// If this is a trait reference, you also need to pass the self type `self_ty`.
|
||||
/// The lowering process may involve applying defaulted type parameters.
|
||||
///
|
||||
/// Associated item bindings are not handled here!
|
||||
/// Associated item constraints are not handled here! They are either lowered via
|
||||
/// `lower_assoc_item_constraint` or rejected via `prohibit_assoc_item_constraint`.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
|
|
@ -349,7 +350,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
/// which will have been resolved to a `def_id`
|
||||
/// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
|
||||
/// parameters are returned in the `GenericArgsRef`
|
||||
/// 4. Associated type bindings like `Output = u32` are contained in `generic_args.bindings`.
|
||||
/// 4. Associated item constraints like `Output = u32` are contained in `generic_args.constraints`.
|
||||
///
|
||||
/// Note that the type listing given here is *exactly* what the user provided.
|
||||
///
|
||||
|
|
@ -403,16 +404,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self_ty.is_some(),
|
||||
);
|
||||
|
||||
if let Err(err) = &arg_count.correct
|
||||
&& let Some(reported) = err.reported
|
||||
{
|
||||
self.set_tainted_by_errors(reported);
|
||||
if let Err(err) = &arg_count.correct {
|
||||
self.set_tainted_by_errors(err.reported);
|
||||
}
|
||||
|
||||
// Skip processing if type has no generic parameters.
|
||||
// Traits always have `Self` as a generic parameter, which means they will not return early
|
||||
// here and so associated type bindings will be handled regardless of whether there are any
|
||||
// non-`Self` generic parameters.
|
||||
// here and so associated item constraints will be handled regardless of whether there are
|
||||
// any non-`Self` generic parameters.
|
||||
if generics.is_own_empty() {
|
||||
return (tcx.mk_args(parent_args), arg_count);
|
||||
}
|
||||
|
|
@ -424,6 +423,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
span: Span,
|
||||
inferred_params: Vec<Span>,
|
||||
infer_args: bool,
|
||||
incorrect_args: &'a Result<(), GenericArgCountMismatch>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for GenericArgsCtxt<'a, 'tcx> {
|
||||
|
|
@ -438,11 +438,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
fn provided_kind(
|
||||
&mut self,
|
||||
preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
arg: &GenericArg<'tcx>,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
let tcx = self.lowerer.tcx();
|
||||
|
||||
if let Err(incorrect) = self.incorrect_args {
|
||||
if incorrect.invalid_args.contains(&(param.index as usize)) {
|
||||
return param.to_error(tcx, preceding_args);
|
||||
}
|
||||
}
|
||||
|
||||
let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {
|
||||
if has_default {
|
||||
tcx.check_optional_stability(
|
||||
|
|
@ -505,11 +512,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
fn inferred_kind(
|
||||
&mut self,
|
||||
args: Option<&[ty::GenericArg<'tcx>]>,
|
||||
preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
infer_args: bool,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
let tcx = self.lowerer.tcx();
|
||||
|
||||
if let Err(incorrect) = self.incorrect_args {
|
||||
if incorrect.invalid_args.contains(&(param.index as usize)) {
|
||||
return param.to_error(tcx, preceding_args);
|
||||
}
|
||||
}
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => self
|
||||
.lowerer
|
||||
|
|
@ -528,15 +541,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
if !infer_args && has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
let args = args.unwrap();
|
||||
if args.iter().any(|arg| match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => ty.references_error(),
|
||||
_ => false,
|
||||
}) {
|
||||
if let Some(prev) =
|
||||
preceding_args.iter().find_map(|arg| match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => ty.error_reported().err(),
|
||||
_ => None,
|
||||
})
|
||||
{
|
||||
// Avoid ICE #86756 when type error recovery goes awry.
|
||||
return Ty::new_misc_error(tcx).into();
|
||||
return Ty::new_error(tcx, prev).into();
|
||||
}
|
||||
tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into()
|
||||
tcx.at(self.span)
|
||||
.type_of(param.def_id)
|
||||
.instantiate(tcx, preceding_args)
|
||||
.into()
|
||||
} else if infer_args {
|
||||
self.lowerer.ty_infer(Some(param), self.span).into()
|
||||
} else {
|
||||
|
|
@ -556,7 +573,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// FIXME(effects) see if we should special case effect params here
|
||||
if !infer_args && has_default {
|
||||
tcx.const_param_default(param.def_id)
|
||||
.instantiate(tcx, args.unwrap())
|
||||
.instantiate(tcx, preceding_args)
|
||||
.into()
|
||||
} else {
|
||||
if infer_args {
|
||||
|
|
@ -570,6 +587,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
|
||||
&& generics.has_self
|
||||
&& !tcx.has_attr(def_id, sym::const_trait)
|
||||
{
|
||||
let reported = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
|
||||
span,
|
||||
modifier: constness.as_str(),
|
||||
});
|
||||
self.set_tainted_by_errors(reported);
|
||||
arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] });
|
||||
}
|
||||
|
||||
let mut args_ctx = GenericArgsCtxt {
|
||||
lowerer: self,
|
||||
|
|
@ -578,19 +606,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
generic_args: segment.args(),
|
||||
inferred_params: vec![],
|
||||
infer_args: segment.infer_args,
|
||||
incorrect_args: &arg_count.correct,
|
||||
};
|
||||
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
|
||||
&& generics.has_self
|
||||
&& !tcx.has_attr(def_id, sym::const_trait)
|
||||
{
|
||||
let e = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
|
||||
span,
|
||||
modifier: constness.as_str(),
|
||||
});
|
||||
self.set_tainted_by_errors(e);
|
||||
arg_count.correct =
|
||||
Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
|
||||
}
|
||||
let args = lower_generic_args(
|
||||
tcx,
|
||||
def_id,
|
||||
|
|
@ -621,8 +638,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
None,
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
prohibit_assoc_item_binding(self.tcx(), b, Some((item_def_id, item_segment, span)));
|
||||
if let Some(c) = item_segment.args().constraints.first() {
|
||||
prohibit_assoc_item_constraint(self.tcx(), c, Some((item_def_id, item_segment, span)));
|
||||
}
|
||||
args
|
||||
}
|
||||
|
|
@ -654,13 +671,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
///
|
||||
/// *Polymorphic* in the sense that it may bind late-bound vars.
|
||||
///
|
||||
/// This may generate auxiliary bounds if the trait reference contains associated item bindings.
|
||||
/// This may generate auxiliary bounds iff the trait reference contains associated item constraints.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// Given the trait ref `Iterator<Item = u32>` and the self type `Ty`, this will add the
|
||||
///
|
||||
/// 1. *trait predicate* `<Ty as Iterator>` (known as `Foo: Iterator` in surface syntax) and the
|
||||
/// 1. *trait predicate* `<Ty as Iterator>` (known as `Ty: Iterator` in the surface syntax) and the
|
||||
/// 2. *projection predicate* `<Ty as Iterator>::Item = u32`
|
||||
///
|
||||
/// to `bounds`.
|
||||
|
|
@ -714,27 +731,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
debug!(?poly_trait_ref);
|
||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
||||
|
||||
let mut dup_bindings = FxIndexMap::default();
|
||||
for binding in trait_segment.args().bindings {
|
||||
// Don't register additional associated type bounds for negative bounds,
|
||||
// since we should have emitten an error for them earlier, and they will
|
||||
// not be well-formed!
|
||||
let mut dup_constraints = FxIndexMap::default();
|
||||
for constraint in trait_segment.args().constraints {
|
||||
// Don't register any associated item constraints for negative bounds,
|
||||
// since we should have emitted an error for them earlier, and they
|
||||
// would not be well-formed!
|
||||
if polarity != ty::PredicatePolarity::Positive {
|
||||
assert!(
|
||||
self.tcx().dcx().has_errors().is_some(),
|
||||
"negative trait bounds should not have bindings",
|
||||
"negative trait bounds should not have assoc item constraints",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Specify type to assert that error was already reported in `Err` case.
|
||||
let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_binding(
|
||||
let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_constraint(
|
||||
trait_ref.hir_ref_id,
|
||||
poly_trait_ref,
|
||||
binding,
|
||||
constraint,
|
||||
bounds,
|
||||
&mut dup_bindings,
|
||||
binding.span,
|
||||
&mut dup_constraints,
|
||||
constraint.span,
|
||||
only_self_bounds,
|
||||
);
|
||||
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
|
||||
|
|
@ -766,8 +783,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
Some(self_ty),
|
||||
constness,
|
||||
);
|
||||
if let Some(b) = trait_segment.args().bindings.first() {
|
||||
prohibit_assoc_item_binding(self.tcx(), b, Some((trait_def_id, trait_segment, span)));
|
||||
if let Some(c) = trait_segment.args().constraints.first() {
|
||||
prohibit_assoc_item_constraint(
|
||||
self.tcx(),
|
||||
c,
|
||||
Some((trait_def_id, trait_segment, span)),
|
||||
);
|
||||
}
|
||||
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
|
||||
}
|
||||
|
|
@ -849,7 +870,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
///
|
||||
/// This fails if there is no such bound in the list of candidates or if there are multiple
|
||||
/// candidates in which case it reports ambiguity.
|
||||
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, binding), ret)]
|
||||
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, constraint), ret)]
|
||||
fn probe_single_bound_for_assoc_item<I>(
|
||||
&self,
|
||||
all_candidates: impl Fn() -> I,
|
||||
|
|
@ -858,7 +879,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
assoc_kind: ty::AssocKind,
|
||||
assoc_name: Ident,
|
||||
span: Span,
|
||||
binding: Option<&hir::TypeBinding<'tcx>>,
|
||||
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
|
||||
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
|
||||
where
|
||||
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||
|
|
@ -877,7 +898,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
assoc_kind,
|
||||
assoc_name,
|
||||
span,
|
||||
binding,
|
||||
constraint,
|
||||
);
|
||||
self.set_tainted_by_errors(reported);
|
||||
return Err(reported);
|
||||
|
|
@ -897,8 +918,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
});
|
||||
// Provide a more specific error code index entry for equality bindings.
|
||||
err.code(
|
||||
if let Some(binding) = binding
|
||||
&& let hir::TypeBindingKind::Equality { .. } = binding.kind
|
||||
if let Some(constraint) = constraint
|
||||
&& let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
|
||||
{
|
||||
E0222
|
||||
} else {
|
||||
|
|
@ -906,7 +927,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
},
|
||||
);
|
||||
|
||||
// FIXME(#97583): Resugar equality bounds to type/const bindings.
|
||||
// FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!).
|
||||
// FIXME: Turn this into a structured, translateable & more actionable suggestion.
|
||||
let mut where_bounds = vec![];
|
||||
for bound in [bound, bound2].into_iter().chain(matching_candidates) {
|
||||
|
|
@ -921,9 +942,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
bound_span,
|
||||
format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),),
|
||||
);
|
||||
if let Some(binding) = binding {
|
||||
match binding.kind {
|
||||
hir::TypeBindingKind::Equality { term } => {
|
||||
if let Some(constraint) = constraint {
|
||||
match constraint.kind {
|
||||
hir::AssocItemConstraintKind::Equality { term } => {
|
||||
let term: ty::Term<'_> = match term {
|
||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||
hir::Term::Const(ct) => {
|
||||
|
|
@ -937,7 +958,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
));
|
||||
}
|
||||
// FIXME: Provide a suggestion.
|
||||
hir::TypeBindingKind::Constraint { bounds: _ } => {}
|
||||
hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
|
||||
}
|
||||
} else {
|
||||
err.span_suggestion_verbose(
|
||||
|
|
@ -1293,7 +1314,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.copied()
|
||||
.filter(|&(impl_, _)| {
|
||||
infcx.probe(|_| {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
|
||||
|
||||
let impl_args = infcx.fresh_args_for_item(span, impl_);
|
||||
|
|
@ -1540,8 +1561,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
for segment in segments {
|
||||
// Only emit the first error to avoid overloading the user with error messages.
|
||||
if let Some(b) = segment.args().bindings.first() {
|
||||
return Err(prohibit_assoc_item_binding(self.tcx(), b, None));
|
||||
if let Some(c) = segment.args().constraints.first() {
|
||||
return Err(prohibit_assoc_item_constraint(self.tcx(), c, None));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ fn diagnostic_hir_wf_check<'tcx>(
|
|||
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
|
||||
let tcx_ty = self.icx.lower_ty(ty);
|
||||
// This visitor can walk into binders, resulting in the `tcx_ty` to
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ fn enforce_impl_params_are_constrained(
|
|||
let impl_predicates = tcx.predicates_of(impl_def_id);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
|
||||
|
||||
impl_trait_ref.error_reported()?;
|
||||
|
||||
let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
|
||||
cgp::identify_constrained_generic_params(
|
||||
tcx,
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ fn get_impl_args(
|
|||
impl2_node: Node,
|
||||
) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> {
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
let param_env = tcx.param_env(impl1_def_id);
|
||||
let impl1_span = tcx.def_span(impl1_def_id);
|
||||
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
|
||||
|
|
|
|||
|
|
@ -489,7 +489,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
.in_definition_order()
|
||||
.filter(|item| item.kind == AssocKind::Type)
|
||||
.filter(|item| {
|
||||
!self.gen_args.bindings.iter().any(|binding| binding.ident.name == item.name)
|
||||
!self
|
||||
.gen_args
|
||||
.constraints
|
||||
.iter()
|
||||
.any(|constraint| constraint.ident.name == item.name)
|
||||
})
|
||||
.map(|item| item.name.to_ident_string())
|
||||
.collect()
|
||||
|
|
@ -679,11 +683,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
(last_lt.span().shrink_to_hi(), false)
|
||||
};
|
||||
let has_non_lt_args = self.num_provided_type_or_const_args() != 0;
|
||||
let has_bindings = !self.gen_args.bindings.is_empty();
|
||||
let has_constraints = !self.gen_args.constraints.is_empty();
|
||||
|
||||
let sugg_prefix = if is_first { "" } else { ", " };
|
||||
let sugg_suffix =
|
||||
if is_first && (has_non_lt_args || has_bindings) { ", " } else { "" };
|
||||
if is_first && (has_non_lt_args || has_constraints) { ", " } else { "" };
|
||||
|
||||
let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
|
||||
debug!("sugg: {:?}", sugg);
|
||||
|
|
@ -741,7 +745,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
|
||||
let sugg_prefix = if is_first { "" } else { ", " };
|
||||
let sugg_suffix =
|
||||
if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" };
|
||||
if is_first && !self.gen_args.constraints.is_empty() { ", " } else { "" };
|
||||
|
||||
let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
|
||||
debug!("sugg: {:?}", sugg);
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ impl<'a> State<'a> {
|
|||
Node::Stmt(a) => self.print_stmt(a),
|
||||
Node::PathSegment(a) => self.print_path_segment(a),
|
||||
Node::Ty(a) => self.print_type(a),
|
||||
Node::TypeBinding(a) => self.print_type_binding(a),
|
||||
Node::AssocItemConstraint(a) => self.print_assoc_item_constraint(a),
|
||||
Node::TraitRef(a) => self.print_trait_ref(a),
|
||||
Node::Pat(a) => self.print_pat(a),
|
||||
Node::PatField(a) => self.print_patfield(a),
|
||||
|
|
@ -1135,7 +1135,7 @@ impl<'a> State<'a> {
|
|||
self.print_ident(segment.ident);
|
||||
|
||||
let generic_args = segment.args();
|
||||
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
|
||||
if !generic_args.args.is_empty() || !generic_args.constraints.is_empty() {
|
||||
self.print_generic_args(generic_args, true);
|
||||
}
|
||||
|
||||
|
|
@ -1676,9 +1676,9 @@ impl<'a> State<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
for binding in generic_args.bindings {
|
||||
for constraint in generic_args.constraints {
|
||||
start_or_comma(self);
|
||||
self.print_type_binding(binding);
|
||||
self.print_assoc_item_constraint(constraint);
|
||||
}
|
||||
|
||||
if !empty.get() {
|
||||
|
|
@ -1686,13 +1686,15 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
hir::GenericArgsParentheses::ParenSugar => {
|
||||
let (inputs, output) = generic_args.paren_sugar_inputs_output().unwrap();
|
||||
|
||||
self.word("(");
|
||||
self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty));
|
||||
self.commasep(Inconsistent, inputs, |s, ty| s.print_type(ty));
|
||||
self.word(")");
|
||||
|
||||
self.space_if_not_bol();
|
||||
self.word_space("->");
|
||||
self.print_type(generic_args.bindings[0].ty());
|
||||
self.print_type(output);
|
||||
}
|
||||
hir::GenericArgsParentheses::ReturnTypeNotation => {
|
||||
self.word("(..)");
|
||||
|
|
@ -1700,19 +1702,19 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_type_binding(&mut self, binding: &hir::TypeBinding<'_>) {
|
||||
self.print_ident(binding.ident);
|
||||
self.print_generic_args(binding.gen_args, false);
|
||||
fn print_assoc_item_constraint(&mut self, constraint: &hir::AssocItemConstraint<'_>) {
|
||||
self.print_ident(constraint.ident);
|
||||
self.print_generic_args(constraint.gen_args, false);
|
||||
self.space();
|
||||
match binding.kind {
|
||||
hir::TypeBindingKind::Equality { ref term } => {
|
||||
match constraint.kind {
|
||||
hir::AssocItemConstraintKind::Equality { ref term } => {
|
||||
self.word_space("=");
|
||||
match term {
|
||||
Term::Ty(ty) => self.print_type(ty),
|
||||
Term::Const(ref c) => self.print_anon_const(c),
|
||||
}
|
||||
}
|
||||
hir::TypeBindingKind::Constraint { bounds } => {
|
||||
hir::AssocItemConstraintKind::Bound { bounds } => {
|
||||
self.print_bounds(":", bounds);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,10 +207,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let hir = self.tcx.hir();
|
||||
|
||||
// First, check that we're actually in the tail of a function.
|
||||
let Some(body_id) = hir.maybe_body_owned_by(self.body_id) else {
|
||||
let Some(body) = hir.maybe_body_owned_by(self.body_id) else {
|
||||
return;
|
||||
};
|
||||
let body = hir.body(body_id);
|
||||
let hir::ExprKind::Block(block, _) = body.value.kind else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
// Since this is a return parameter type it is safe to unwrap.
|
||||
let ret_param_ty = projection.skip_binder().term.ty().unwrap();
|
||||
let ret_param_ty = projection.skip_binder().term.expect_type();
|
||||
let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty);
|
||||
debug!(?ret_param_ty);
|
||||
|
||||
|
|
@ -956,7 +956,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let output_ty = self.resolve_vars_if_possible(predicate.term);
|
||||
debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
|
||||
// This is a projection on a Fn trait so will always be a type.
|
||||
Some(output_ty.ty().unwrap())
|
||||
Some(output_ty.expect_type())
|
||||
}
|
||||
|
||||
/// Converts the types that the user supplied, in case that doing
|
||||
|
|
|
|||
|
|
@ -327,8 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() };
|
||||
let body =
|
||||
hir.body(hir.maybe_body_owned_by(self.body_id).expect("expected item to have body"));
|
||||
let body = hir.body_owned_by(self.body_id);
|
||||
expr_finder.visit_expr(body.value);
|
||||
|
||||
// Replaces all of the variables in the given type with a fresh inference variable.
|
||||
|
|
|
|||
|
|
@ -909,8 +909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// the first place.
|
||||
assert_ne!(encl_item_id.def_id, encl_body_owner_id);
|
||||
|
||||
let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id);
|
||||
let encl_body = self.tcx.hir().body(encl_body_id);
|
||||
let encl_body = self.tcx.hir().body_owned_by(encl_body_owner_id);
|
||||
|
||||
err.encl_body_span = Some(encl_body.value.span);
|
||||
err.encl_fn_span = Some(*encl_fn_span);
|
||||
|
|
@ -1348,6 +1347,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some(rcvr),
|
||||
rcvr_t,
|
||||
segment.ident,
|
||||
expr.hir_id,
|
||||
SelfSource::MethodCall(rcvr),
|
||||
error,
|
||||
Some(args),
|
||||
|
|
@ -3049,7 +3049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.commit_if_ok(|snapshot| {
|
||||
let outer_universe = self.universe();
|
||||
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(self);
|
||||
let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
|
||||
let impl_trait_ref =
|
||||
self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args);
|
||||
|
|
|
|||
|
|
@ -544,9 +544,8 @@ fn compute_unsafe_infer_vars<'a, 'tcx>(
|
|||
root_ctxt: &'a TypeckRootCtxt<'tcx>,
|
||||
body_id: LocalDefId,
|
||||
) -> UnordMap<ty::TyVid, (HirId, Span, UnsafeUseReason)> {
|
||||
let body_id =
|
||||
let body =
|
||||
root_ctxt.tcx.hir().maybe_body_owned_by(body_id).expect("body id must have an owner");
|
||||
let body = root_ctxt.tcx.hir().body(body_id);
|
||||
let mut res = UnordMap::default();
|
||||
|
||||
struct UnsafeInferVarsVisitor<'a, 'tcx, 'r> {
|
||||
|
|
|
|||
|
|
@ -832,6 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
None,
|
||||
ty.normalized,
|
||||
item_name,
|
||||
hir_id,
|
||||
SelfSource::QPath(qself),
|
||||
error,
|
||||
args,
|
||||
|
|
@ -1117,7 +1118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// to add defaults. If the user provided *too many* types, that's
|
||||
// a problem.
|
||||
|
||||
let mut infer_args_for_err = FxHashSet::default();
|
||||
let mut infer_args_for_err = None;
|
||||
|
||||
let mut explicit_late_bound = ExplicitLateBound::No;
|
||||
for &GenericPathSegment(def_id, index) in &generic_segments {
|
||||
|
|
@ -1135,9 +1136,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
explicit_late_bound = ExplicitLateBound::Yes;
|
||||
}
|
||||
|
||||
if let Err(GenericArgCountMismatch { reported: Some(e), .. }) = arg_count.correct {
|
||||
infer_args_for_err.insert(index);
|
||||
self.set_tainted_by_errors(e); // See issue #53251.
|
||||
if let Err(GenericArgCountMismatch { reported, .. }) = arg_count.correct {
|
||||
infer_args_for_err
|
||||
.get_or_insert_with(|| (reported, FxHashSet::default()))
|
||||
.1
|
||||
.insert(index);
|
||||
self.set_tainted_by_errors(reported); // See issue #53251.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1231,15 +1235,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
let def_id = res.def_id();
|
||||
|
||||
let arg_count = GenericArgCountResult {
|
||||
explicit_late_bound,
|
||||
correct: if infer_args_for_err.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(GenericArgCountMismatch::default())
|
||||
},
|
||||
let (correct, infer_args_for_err) = match infer_args_for_err {
|
||||
Some((reported, args)) => {
|
||||
(Err(GenericArgCountMismatch { reported, invalid_args: vec![] }), args)
|
||||
}
|
||||
None => (Ok(()), Default::default()),
|
||||
};
|
||||
|
||||
let arg_count = GenericArgCountResult { explicit_late_bound, correct };
|
||||
|
||||
struct CtorGenericArgsCtxt<'a, 'tcx> {
|
||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
|
|
@ -1271,6 +1275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
fn provided_kind(
|
||||
&mut self,
|
||||
_preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
arg: &GenericArg<'tcx>,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
|
|
@ -1313,7 +1318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
fn inferred_kind(
|
||||
&mut self,
|
||||
args: Option<&[ty::GenericArg<'tcx>]>,
|
||||
preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
infer_args: bool,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
|
|
@ -1327,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// If we have a default, then it doesn't matter that we're not
|
||||
// inferring the type arguments: we provide the default where any
|
||||
// is missing.
|
||||
tcx.type_of(param.def_id).instantiate(tcx, args.unwrap()).into()
|
||||
tcx.type_of(param.def_id).instantiate(tcx, preceding_args).into()
|
||||
} else {
|
||||
// If no type arguments were provided, we have to infer them.
|
||||
// This case also occurs as a result of some malformed input, e.g.
|
||||
|
|
@ -1352,7 +1357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else if !infer_args {
|
||||
return tcx
|
||||
.const_param_default(param.def_id)
|
||||
.instantiate(tcx, args.unwrap())
|
||||
.instantiate(tcx, preceding_args)
|
||||
.into();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ use rustc_hir::{
|
|||
};
|
||||
use rustc_hir_analysis::collect::suggest_impl_trait;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_infer::traits;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::span_bug;
|
||||
|
|
@ -36,6 +35,7 @@ use rustc_span::source_map::Spanned;
|
|||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
|
|
@ -848,19 +848,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds
|
||||
&& let Some(hir::PathSegment { args: Some(generic_args), .. }) =
|
||||
trait_ref.trait_ref.path.segments.last()
|
||||
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
|
||||
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(term) } =
|
||||
ty_binding.kind
|
||||
&& let [constraint] = generic_args.constraints
|
||||
&& let Some(ty) = constraint.ty()
|
||||
{
|
||||
// Check if async function's return type was omitted.
|
||||
// Don't emit suggestions if the found type is `impl Future<...>`.
|
||||
debug!(?found);
|
||||
if found.is_suggestable(self.tcx, false) {
|
||||
if term.span.is_empty() {
|
||||
if ty.span.is_empty() {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::AddReturnTypeSuggestion::Add {
|
||||
span: term.span,
|
||||
span: ty.span,
|
||||
found: found.to_string(),
|
||||
},
|
||||
);
|
||||
|
|
@ -868,10 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::ExpectedReturnTypeLabel::Other {
|
||||
span: term.span,
|
||||
expected,
|
||||
},
|
||||
errors::ExpectedReturnTypeLabel::Other { span: ty.span, expected },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1973,8 +1969,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
*expr
|
||||
} else {
|
||||
let body_def_id = hir.enclosing_body_owner(expr.hir_id);
|
||||
let body_id = hir.body_owned_by(body_def_id);
|
||||
let body = hir.body(body_id);
|
||||
let body = hir.body_owned_by(body_def_id);
|
||||
|
||||
// Get tail expr of the body
|
||||
match body.value.kind {
|
||||
|
|
|
|||
|
|
@ -383,6 +383,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
|
||||
fn provided_kind(
|
||||
&mut self,
|
||||
_preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
arg: &GenericArg<'tcx>,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
|
|
@ -419,7 +420,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
|
||||
fn inferred_kind(
|
||||
&mut self,
|
||||
_args: Option<&[ty::GenericArg<'tcx>]>,
|
||||
_preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
_infer_args: bool,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
|
|
|
|||
|
|
@ -1390,7 +1390,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
|
||||
let mut result = ProbeResult::Match;
|
||||
let cause = &self.misc(self.span);
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(self);
|
||||
|
||||
let mut trait_predicate = None;
|
||||
let (mut xform_self_ty, mut xform_ret_ty);
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: Ident,
|
||||
expr_id: hir::HirId,
|
||||
source: SelfSource<'tcx>,
|
||||
error: MethodError<'tcx>,
|
||||
args: Option<&'tcx [hir::Expr<'tcx>]>,
|
||||
|
|
@ -216,6 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
rcvr_opt,
|
||||
rcvr_ty,
|
||||
item_name,
|
||||
expr_id,
|
||||
source,
|
||||
args,
|
||||
sugg_span,
|
||||
|
|
@ -505,9 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& let hir::def::Res::Local(recv_id) = path.res
|
||||
&& let Some(segment) = path.segments.first()
|
||||
{
|
||||
let map = self.infcx.tcx.hir();
|
||||
let body_id = self.tcx.hir().body_owned_by(self.body_id);
|
||||
let body = map.body(body_id);
|
||||
let body = self.tcx.hir().body_owned_by(self.body_id);
|
||||
|
||||
if let Node::Expr(call_expr) = self.tcx.parent_hir_node(rcvr.hir_id) {
|
||||
let mut let_visitor = LetVisitor {
|
||||
|
|
@ -518,7 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
method_name,
|
||||
sugg_let: None,
|
||||
};
|
||||
let_visitor.visit_body(body);
|
||||
let_visitor.visit_body(&body);
|
||||
if let Some(sugg_let) = let_visitor.sugg_let
|
||||
&& let Some(self_ty) = self.node_ty_opt(sugg_let.init_hir_id)
|
||||
{
|
||||
|
|
@ -551,6 +551,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: Ident,
|
||||
expr_id: hir::HirId,
|
||||
source: SelfSource<'tcx>,
|
||||
args: Option<&'tcx [hir::Expr<'tcx>]>,
|
||||
sugg_span: Span,
|
||||
|
|
@ -683,7 +684,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
if matches!(source, SelfSource::QPath(_)) && args.is_some() {
|
||||
self.find_builder_fn(&mut err, rcvr_ty);
|
||||
self.find_builder_fn(&mut err, rcvr_ty, expr_id);
|
||||
}
|
||||
|
||||
if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
|
||||
|
|
@ -1944,7 +1945,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// Look at all the associated functions without receivers in the type's inherent impls
|
||||
/// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
|
||||
fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>) {
|
||||
fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>, expr_id: hir::HirId) {
|
||||
let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -1953,8 +1954,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut items = impls
|
||||
.iter()
|
||||
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
|
||||
// Only assoc fn with no receivers.
|
||||
.filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter)
|
||||
// Only assoc fn with no receivers and only if
|
||||
// they are resolvable
|
||||
.filter(|item| {
|
||||
matches!(item.kind, ty::AssocKind::Fn)
|
||||
&& !item.fn_has_self_parameter
|
||||
&& self
|
||||
.probe_for_name(
|
||||
Mode::Path,
|
||||
item.ident(self.tcx),
|
||||
None,
|
||||
IsSuggestion(true),
|
||||
rcvr_ty,
|
||||
expr_id,
|
||||
ProbeScope::TraitsInScope,
|
||||
)
|
||||
.is_ok()
|
||||
})
|
||||
.filter_map(|item| {
|
||||
// Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`.
|
||||
let ret_ty = self
|
||||
|
|
@ -2429,9 +2445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
seg1.ident.span,
|
||||
StashKey::CallAssocMethod,
|
||||
|err| {
|
||||
let map = self.infcx.tcx.hir();
|
||||
let body_id = self.tcx.hir().body_owned_by(self.body_id);
|
||||
let body = map.body(body_id);
|
||||
let body = self.tcx.hir().body_owned_by(self.body_id);
|
||||
struct LetVisitor {
|
||||
ident_name: Symbol,
|
||||
}
|
||||
|
|
@ -2453,7 +2467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id)
|
||||
&& let ControlFlow::Break(Some(expr)) =
|
||||
(LetVisitor { ident_name: seg1.ident.name }).visit_body(body)
|
||||
(LetVisitor { ident_name: seg1.ident.name }).visit_body(&body)
|
||||
&& let Some(self_ty) = self.node_ty_opt(expr.hir_id)
|
||||
{
|
||||
let probe = self.lookup_probe_for_diagnostic(
|
||||
|
|
|
|||
|
|
@ -928,7 +928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let (obligation, _) =
|
||||
self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
|
||||
// FIXME: This should potentially just add the obligation to the `FnCtxt`
|
||||
let ocx = ObligationCtxt::new(&self.infcx);
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
|
||||
ocx.register_obligation(obligation);
|
||||
Err(ocx.select_all_or_error())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
|
|||
use rustc_span::def_id::LocalDefIdMap;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _};
|
||||
use rustc_trait_selection::traits::{
|
||||
self, FulfillmentError, PredicateObligation, TraitEngine, TraitEngineExt as _,
|
||||
};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Deref;
|
||||
|
|
@ -34,7 +36,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
|
|||
|
||||
pub(super) locals: RefCell<HirIdMap<Ty<'tcx>>>,
|
||||
|
||||
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
|
||||
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>,
|
||||
|
||||
/// Some additional `Sized` obligations badly affect type inference.
|
||||
/// These obligations are added in a later stage of typeck.
|
||||
|
|
@ -83,7 +85,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
|
|||
|
||||
TypeckRootCtxt {
|
||||
typeck_results,
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(&infcx)),
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)),
|
||||
infcx,
|
||||
locals: RefCell::new(Default::default()),
|
||||
deferred_sized_obligations: RefCell::new(Vec::new()),
|
||||
|
|
@ -158,7 +160,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
|
|||
{
|
||||
// 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.term.ty().and_then(|ty| ty.ty_vid()) {
|
||||
if let Some(vid) = predicate.term.as_type().and_then(|ty| ty.ty_vid()) {
|
||||
debug!("infer_var_info: {:?}.output = true", vid);
|
||||
infer_var_info.entry(vid).or_default().output = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -865,6 +865,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
|
|||
self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
|
||||
ty::Const::new_error(tcx, guar, ct.ty())
|
||||
})
|
||||
.super_fold_with(self)
|
||||
}
|
||||
|
||||
fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
|||
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult};
|
||||
use crate::traits::query::NoSolution;
|
||||
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
|
||||
use crate::traits::{TraitEngine, TraitEngineExt};
|
||||
use crate::traits::{ScrubbedTraitError, TraitEngine};
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_index::Idx;
|
||||
use rustc_index::IndexVec;
|
||||
|
|
@ -54,7 +54,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
&self,
|
||||
inference_vars: CanonicalVarValues<'tcx>,
|
||||
answer: T,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
|
||||
) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
|
||||
where
|
||||
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
|
|
@ -101,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
&self,
|
||||
inference_vars: CanonicalVarValues<'tcx>,
|
||||
answer: T,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
|
||||
) -> Result<QueryResponse<'tcx, T>, NoSolution>
|
||||
where
|
||||
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
|
|
@ -109,19 +109,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let tcx = self.tcx;
|
||||
|
||||
// Select everything, returning errors.
|
||||
let true_errors = fulfill_cx.select_where_possible(self);
|
||||
debug!("true_errors = {:#?}", true_errors);
|
||||
let errors = fulfill_cx.select_all_or_error(self);
|
||||
|
||||
if !true_errors.is_empty() {
|
||||
// FIXME -- we don't indicate *why* we failed to solve
|
||||
debug!("make_query_response: true_errors={:#?}", true_errors);
|
||||
// True error!
|
||||
if errors.iter().any(|e| e.is_true_error()) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// Anything left unselected *now* must be an ambiguity.
|
||||
let ambig_errors = fulfill_cx.select_all_or_error(self);
|
||||
debug!("ambig_errors = {:#?}", ambig_errors);
|
||||
|
||||
let region_obligations = self.take_registered_region_obligations();
|
||||
debug!(?region_obligations);
|
||||
let region_constraints = self.with_region_constraints(|region_constraints| {
|
||||
|
|
@ -135,8 +129,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
});
|
||||
debug!(?region_constraints);
|
||||
|
||||
let certainty =
|
||||
if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
|
||||
let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
|
||||
|
||||
let opaque_types = self.take_opaque_types_for_query_response();
|
||||
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
ty::ClauseKind::Projection(projection_predicate)
|
||||
if projection_predicate.projection_term.def_id == item_def_id =>
|
||||
{
|
||||
projection_predicate.term.ty()
|
||||
projection_predicate.term.as_type()
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -457,10 +457,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
};
|
||||
|
||||
let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
|
||||
if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(
|
||||
if let Some(body) = self.tcx.hir().maybe_body_owned_by(
|
||||
self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
|
||||
) {
|
||||
let expr = self.tcx.hir().body(body_id).value;
|
||||
let expr = body.value;
|
||||
local_visitor.visit_expr(expr);
|
||||
}
|
||||
|
||||
|
|
@ -1163,7 +1163,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
|
|||
|
||||
/// For closures, we first visit the parameters and then the content,
|
||||
/// as we prefer those.
|
||||
fn visit_body(&mut self, body: &'tcx Body<'tcx>) {
|
||||
fn visit_body(&mut self, body: &Body<'tcx>) {
|
||||
for param in body.params {
|
||||
debug!(
|
||||
"param: span {:?}, ty_span {:?}, pat.span {:?}",
|
||||
|
|
|
|||
|
|
@ -62,14 +62,13 @@ pub fn find_param_with_region<'tcx>(
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let body_id = hir.maybe_body_owned_by(def_id)?;
|
||||
let body = hir.maybe_body_owned_by(def_id)?;
|
||||
|
||||
let owner_id = hir.body_owner(body_id);
|
||||
let owner_id = hir.body_owner(body.id());
|
||||
let fn_decl = hir.fn_decl_by_hir_id(owner_id)?;
|
||||
let poly_fn_sig = tcx.fn_sig(id).instantiate_identity();
|
||||
|
||||
let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig);
|
||||
let body = hir.body(body_id);
|
||||
body.params
|
||||
.iter()
|
||||
.take(if fn_sig.c_variadic {
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
diag.span_label(p_span, format!("{expected}this type parameter"));
|
||||
}
|
||||
diag.help("type parameters must be constrained to match other types");
|
||||
if tcx.sess.teach(diag.code.unwrap()) {
|
||||
if diag.code.is_some_and(|code| tcx.sess.teach(code)) {
|
||||
diag.help(
|
||||
"given a type parameter `T` and a method `foo`:
|
||||
```
|
||||
|
|
@ -663,7 +663,7 @@ impl<T> Trait<T> for X {
|
|||
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
|
||||
);
|
||||
}
|
||||
if tcx.sess.teach(diag.code.unwrap()) {
|
||||
if diag.code.is_some_and(|code| tcx.sess.teach(code)) {
|
||||
diag.help(
|
||||
"given an associated type `T` and a method `foo`:
|
||||
```
|
||||
|
|
|
|||
|
|
@ -578,16 +578,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
walk_stmt(self, ex)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, body: &'v hir::Body<'v>) -> Self::Result {
|
||||
hir::intravisit::walk_body(self, body)
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body_id| {
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body| {
|
||||
IfVisitor { err_span: span, found_if: false }
|
||||
.visit_body(body)
|
||||
.visit_body(&body)
|
||||
.is_break()
|
||||
.then(|| TypeErrorAdditionalDiags::AddLetForLetChains { span: span.shrink_to_lo() })
|
||||
})
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
use super::InferCtxt;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::infer::unify_key::ToType;
|
||||
use rustc_middle::ty::fold::TypeFolder;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
|
@ -204,22 +203,27 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
|
|||
|
||||
ty::IntVar(v) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let input = inner
|
||||
.int_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.ok_or_else(|| ty::IntVar(inner.int_unification_table().find(v)));
|
||||
let value = inner.int_unification_table().probe_value(v);
|
||||
let input = match value {
|
||||
ty::IntVarValue::IntType(ty) => Ok(Ty::new_int(self.infcx.tcx, ty)),
|
||||
ty::IntVarValue::UintType(ty) => Ok(Ty::new_uint(self.infcx.tcx, ty)),
|
||||
ty::IntVarValue::Unknown => {
|
||||
Err(ty::IntVar(inner.int_unification_table().find(v)))
|
||||
}
|
||||
};
|
||||
drop(inner);
|
||||
Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n)))
|
||||
}
|
||||
|
||||
ty::FloatVar(v) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let input = inner
|
||||
.float_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.ok_or_else(|| ty::FloatVar(inner.float_unification_table().find(v)));
|
||||
let value = inner.float_unification_table().probe_value(v);
|
||||
let input = match value {
|
||||
ty::FloatVarValue::Known(ty) => Ok(Ty::new_float(self.infcx.tcx, ty)),
|
||||
ty::FloatVarValue::Unknown => {
|
||||
Err(ty::FloatVar(inner.float_unification_table().find(v)))
|
||||
}
|
||||
};
|
||||
drop(inner);
|
||||
Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub use SubregionOrigin::*;
|
|||
pub use ValuePairs::*;
|
||||
|
||||
use crate::traits::{
|
||||
self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt,
|
||||
self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
|
||||
};
|
||||
use error_reporting::TypeErrCtxt;
|
||||
use free_regions::RegionRelations;
|
||||
|
|
@ -29,9 +29,9 @@ use rustc_errors::{Diag, DiagCtxt, ErrorGuaranteed};
|
|||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
|
||||
use rustc_middle::infer::unify_key::ConstVariableOrigin;
|
||||
use rustc_middle::infer::unify_key::ConstVariableValue;
|
||||
use rustc_middle::infer::unify_key::EffectVarValue;
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ToType};
|
||||
use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
|
||||
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
|
|
@ -41,7 +41,7 @@ use rustc_middle::ty::fold::BoundVarReplacerDelegate;
|
|||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
|
||||
use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
|
@ -424,8 +424,8 @@ pub enum ValuePairs<'tcx> {
|
|||
impl<'tcx> ValuePairs<'tcx> {
|
||||
pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
|
||||
if let ValuePairs::Terms(ExpectedFound { expected, found }) = self
|
||||
&& let Some(expected) = expected.ty()
|
||||
&& let Some(found) = found.ty()
|
||||
&& let Some(expected) = expected.as_type()
|
||||
&& let Some(found) = found.as_type()
|
||||
{
|
||||
Some((expected, found))
|
||||
} else {
|
||||
|
|
@ -587,6 +587,7 @@ pub enum FixupError {
|
|||
UnresolvedFloatTy(FloatVid),
|
||||
UnresolvedTy(TyVid),
|
||||
UnresolvedConst(ConstVid),
|
||||
UnresolvedEffect(EffectVid),
|
||||
}
|
||||
|
||||
/// See the `region_obligations` field for more information.
|
||||
|
|
@ -614,6 +615,7 @@ impl fmt::Display for FixupError {
|
|||
),
|
||||
UnresolvedTy(_) => write!(f, "unconstrained type"),
|
||||
UnresolvedConst(_) => write!(f, "unconstrained const value"),
|
||||
UnresolvedEffect(_) => write!(f, "unconstrained effect value"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -737,10 +739,10 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
|
||||
impl<'tcx, T> InferOk<'tcx, T> {
|
||||
/// Extracts `value`, registering any obligations into `fulfill_cx`.
|
||||
pub fn into_value_registering_obligations(
|
||||
pub fn into_value_registering_obligations<E: 'tcx>(
|
||||
self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||
) -> T {
|
||||
let InferOk { value, obligations } = self;
|
||||
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
||||
|
|
@ -811,13 +813,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
vars.extend(
|
||||
(0..inner.int_unification_table().len())
|
||||
.map(|i| ty::IntVid::from_u32(i as u32))
|
||||
.filter(|&vid| inner.int_unification_table().probe_value(vid).is_none())
|
||||
.filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
|
||||
.map(|v| Ty::new_int_var(self.tcx, v)),
|
||||
);
|
||||
vars.extend(
|
||||
(0..inner.float_unification_table().len())
|
||||
.map(|i| ty::FloatVid::from_u32(i as u32))
|
||||
.filter(|&vid| inner.float_unification_table().probe_value(vid).is_none())
|
||||
.filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
|
||||
.map(|v| Ty::new_float_var(self.tcx, v)),
|
||||
);
|
||||
vars
|
||||
|
|
@ -1025,14 +1027,28 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
ty::Const::new_var(self.tcx, vid, ty)
|
||||
}
|
||||
|
||||
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table()
|
||||
.new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
|
||||
.vid
|
||||
}
|
||||
|
||||
fn next_int_var_id(&self) -> IntVid {
|
||||
self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown)
|
||||
}
|
||||
|
||||
pub fn next_int_var(&self) -> Ty<'tcx> {
|
||||
let vid = self.inner.borrow_mut().int_unification_table().new_key(None);
|
||||
Ty::new_int_var(self.tcx, vid)
|
||||
Ty::new_int_var(self.tcx, self.next_int_var_id())
|
||||
}
|
||||
|
||||
fn next_float_var_id(&self) -> FloatVid {
|
||||
self.inner.borrow_mut().float_unification_table().new_key(ty::FloatVarValue::Unknown)
|
||||
}
|
||||
|
||||
pub fn next_float_var(&self) -> Ty<'tcx> {
|
||||
let vid = self.inner.borrow_mut().float_unification_table().new_key(None);
|
||||
Ty::new_float_var(self.tcx, vid)
|
||||
Ty::new_float_var(self.tcx, self.next_float_var_id())
|
||||
}
|
||||
|
||||
/// Creates a fresh region variable with the next available index.
|
||||
|
|
@ -1234,45 +1250,44 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
|
||||
pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
|
||||
}
|
||||
if let ty::Infer(v) = *ty.kind() {
|
||||
match v {
|
||||
ty::TyVar(v) => {
|
||||
// Not entirely obvious: if `typ` is a type variable,
|
||||
// it can be resolved to an int/float variable, which
|
||||
// can then be recursively resolved, hence the
|
||||
// recursion. Note though that we prevent type
|
||||
// variables from unifying to other type variables
|
||||
// directly (though they may be embedded
|
||||
// structurally), and we prevent cycles in any case,
|
||||
// so this recursion should always be of very limited
|
||||
// depth.
|
||||
//
|
||||
// Note: if these two lines are combined into one we get
|
||||
// dynamic borrow errors on `self.inner`.
|
||||
let known = self.inner.borrow_mut().type_variables().probe(v).known();
|
||||
known.map_or(ty, |t| self.shallow_resolve(t))
|
||||
}
|
||||
|
||||
// This is separate from `shallow_resolve` to keep that method small and inlinable.
|
||||
#[inline(never)]
|
||||
fn fold_infer_ty(&self, v: InferTy) -> Option<Ty<'tcx>> {
|
||||
match v {
|
||||
ty::TyVar(v) => {
|
||||
// Not entirely obvious: if `typ` is a type variable,
|
||||
// it can be resolved to an int/float variable, which
|
||||
// can then be recursively resolved, hence the
|
||||
// recursion. Note though that we prevent type
|
||||
// variables from unifying to other type variables
|
||||
// directly (though they may be embedded
|
||||
// structurally), and we prevent cycles in any case,
|
||||
// so this recursion should always be of very limited
|
||||
// depth.
|
||||
//
|
||||
// Note: if these two lines are combined into one we get
|
||||
// dynamic borrow errors on `self.inner`.
|
||||
let known = self.inner.borrow_mut().type_variables().probe(v).known();
|
||||
known.map(|t| self.shallow_resolve(t))
|
||||
ty::IntVar(v) => {
|
||||
match self.inner.borrow_mut().int_unification_table().probe_value(v) {
|
||||
ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
|
||||
ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
|
||||
ty::IntVarValue::Unknown => ty,
|
||||
}
|
||||
}
|
||||
|
||||
ty::FloatVar(v) => {
|
||||
match self.inner.borrow_mut().float_unification_table().probe_value(v) {
|
||||
ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
|
||||
ty::FloatVarValue::Unknown => ty,
|
||||
}
|
||||
}
|
||||
|
||||
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => ty,
|
||||
}
|
||||
|
||||
ty::IntVar(v) => self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.tcx)),
|
||||
|
||||
ty::FloatVar(v) => self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.tcx)),
|
||||
|
||||
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1321,10 +1336,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
/// or else the root int var in the unification table.
|
||||
pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
if let Some(value) = inner.int_unification_table().probe_value(vid) {
|
||||
value.to_type(self.tcx)
|
||||
} else {
|
||||
Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid))
|
||||
let value = inner.int_unification_table().probe_value(vid);
|
||||
match value {
|
||||
ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
|
||||
ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
|
||||
ty::IntVarValue::Unknown => {
|
||||
Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1332,10 +1350,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
/// or else the root float var in the unification table.
|
||||
pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
if let Some(value) = inner.float_unification_table().probe_value(vid) {
|
||||
value.to_type(self.tcx)
|
||||
} else {
|
||||
Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid))
|
||||
let value = inner.float_unification_table().probe_value(vid);
|
||||
match value {
|
||||
ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
|
||||
ty::FloatVarValue::Unknown => {
|
||||
Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1626,7 +1646,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// If `inlined_probe_value` returns a value it's always a
|
||||
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
|
||||
// `ty::Infer(_)`.
|
||||
self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_some()
|
||||
self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
|
||||
}
|
||||
|
||||
TyOrConstInferVar::TyFloat(v) => {
|
||||
|
|
@ -1634,7 +1654,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
|
||||
//
|
||||
// Not `inlined_probe_value(v)` because this call site is colder.
|
||||
self.inner.borrow_mut().float_unification_table().probe_value(v).is_some()
|
||||
self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
|
||||
}
|
||||
|
||||
TyOrConstInferVar::Const(v) => {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue