Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-06-05 05:13:31 +00:00
commit 7950562142
1369 changed files with 15150 additions and 10219 deletions

View file

@ -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"

View file

@ -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 },
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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)
}

View file

@ -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)
})
}

View file

@ -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),
};

View file

@ -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),

View file

@ -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`.

View file

@ -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) {

View file

@ -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;

View file

@ -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);

View file

@ -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(()),
}

View file

@ -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;

View file

@ -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
};

View file

@ -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, _) => {

View file

@ -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 {

View file

@ -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,

View file

@ -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

View file

@ -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",
)

View file

@ -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

View file

@ -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={:?}",

View file

@ -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".

View file

@ -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();

View file

@ -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.

View file

@ -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

View file

@ -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,

View file

@ -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 }
}
}
}

View file

@ -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;

View file

@ -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};

View file

@ -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;

View file

@ -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(()),

View file

@ -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};

View file

@ -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

View file

@ -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();

View file

@ -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,

View file

@ -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(

View file

@ -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,

View file

@ -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};

View file

@ -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);

View file

@ -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.

View file

@ -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)
}

View file

@ -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)?)?;

View file

@ -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)
}

View file

@ -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.

View file

@ -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}="))
}
}
}
}

View file

@ -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 {

View file

@ -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;

View file

@ -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

View file

@ -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:

View file

@ -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]`.

View file

@ -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;

View file

@ -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()
}

View file

@ -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);

View file

@ -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

View file

@ -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));
}

View file

@ -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(),
)
{

View file

@ -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 {

View file

@ -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

View file

@ -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();

View file

@ -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();

View file

@ -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()

View file

@ -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();

View file

@ -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),
));
}

View file

@ -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!(

View file

@ -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
};

View file

@ -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));
}
}
}

View file

@ -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)

View file

@ -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,

View file

@ -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 {

View file

@ -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());

View file

@ -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(&param) = 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(&param)) => {
// 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 }),
}
}

View file

@ -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;

View file

@ -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));
}
}

View file

@ -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

View file

@ -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,

View file

@ -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)?;

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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;
};

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -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> {

View file

@ -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();
}
}

View file

@ -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 {

View file

@ -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> {

View file

@ -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);

View file

@ -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(

View file

@ -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())
}

View file

@ -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;
}

View file

@ -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> {

View file

@ -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();

View file

@ -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,
})

View file

@ -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 {:?}",

View file

@ -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 {

View file

@ -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`:
```

View file

@ -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() })
})

View file

@ -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)))
}

View file

@ -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