mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
Merge from rustc
This commit is contained in:
commit
ee57d2b318
15
Cargo.lock
15
Cargo.lock
@ -574,7 +574,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||
|
||||
[[package]]
|
||||
name = "clippy"
|
||||
version = "0.1.78"
|
||||
version = "0.1.79"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"clippy_config",
|
||||
@ -602,7 +602,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_config"
|
||||
version = "0.1.78"
|
||||
version = "0.1.79"
|
||||
dependencies = [
|
||||
"rustc-semver",
|
||||
"serde",
|
||||
@ -625,7 +625,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.78"
|
||||
version = "0.1.79"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"cargo_metadata 0.18.1",
|
||||
@ -650,7 +650,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.78"
|
||||
version = "0.1.79"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"clippy_config",
|
||||
@ -971,7 +971,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
|
||||
|
||||
[[package]]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.78"
|
||||
version = "0.1.79"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"quote",
|
||||
@ -2205,7 +2205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.4",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4236,6 +4236,7 @@ name = "rustc_middle"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"derivative",
|
||||
"either",
|
||||
"field-offset",
|
||||
"gsgdt",
|
||||
@ -4440,6 +4441,8 @@ dependencies = [
|
||||
"rustc_target",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -303,10 +303,6 @@ impl TraitBoundModifiers {
|
||||
};
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// `typeck::collect::compute_bounds` matches these against
|
||||
/// the "special" built-in traits (see `middle::lang_items`) and
|
||||
/// detects `Copy`, `Send` and `Sync`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum GenericBound {
|
||||
Trait(PolyTraitRef, TraitBoundModifiers),
|
||||
@ -621,7 +617,9 @@ impl Pat {
|
||||
| PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),
|
||||
|
||||
// Trivial wrappers over inner patterns.
|
||||
PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
|
||||
PatKind::Box(s) | PatKind::Deref(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => {
|
||||
s.walk(it)
|
||||
}
|
||||
|
||||
// These patterns do not contain subpatterns, skip.
|
||||
PatKind::Wild
|
||||
@ -792,6 +790,9 @@ pub enum PatKind {
|
||||
/// A `box` pattern.
|
||||
Box(P<Pat>),
|
||||
|
||||
/// A `deref` pattern (currently `deref!()` macro-based syntax).
|
||||
Deref(P<Pat>),
|
||||
|
||||
/// A reference pattern (e.g., `&mut (a, b)`).
|
||||
Ref(P<Pat>, Mutability),
|
||||
|
||||
@ -1436,7 +1437,7 @@ pub enum ExprKind {
|
||||
/// `'label: loop { block }`
|
||||
Loop(P<Block>, Option<Label>, Span),
|
||||
/// A `match` block.
|
||||
Match(P<Expr>, ThinVec<Arm>),
|
||||
Match(P<Expr>, ThinVec<Arm>, MatchKind),
|
||||
/// A closure (e.g., `move |a, b, c| a + b + c`).
|
||||
Closure(Box<Closure>),
|
||||
/// A block (`'label: { ... }`).
|
||||
@ -1761,6 +1762,15 @@ pub enum StrStyle {
|
||||
Raw(u8),
|
||||
}
|
||||
|
||||
/// The kind of match expression
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
|
||||
pub enum MatchKind {
|
||||
/// match expr { ... }
|
||||
Prefix,
|
||||
/// expr.match { ... }
|
||||
Postfix,
|
||||
}
|
||||
|
||||
/// A literal in a meta item.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct MetaItemLit {
|
||||
|
@ -16,7 +16,6 @@
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
#![cfg_attr(bootstrap, feature(min_specialization))]
|
||||
#![feature(never_type)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
@ -1295,6 +1295,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
||||
fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
|
||||
}
|
||||
PatKind::Box(inner) => vis.visit_pat(inner),
|
||||
PatKind::Deref(inner) => vis.visit_pat(inner),
|
||||
PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
|
||||
PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
|
||||
visit_opt(e1, |e| vis.visit_expr(e));
|
||||
@ -1424,7 +1425,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::Match(expr, arms) => {
|
||||
ExprKind::Match(expr, arms, _kind) => {
|
||||
vis.visit_expr(expr);
|
||||
arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
#[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint.
|
||||
#[allow(hidden_glob_reexports)]
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{edition::Edition, ErrorGuaranteed, Span, DUMMY_SP};
|
||||
@ -104,7 +105,7 @@ impl Lit {
|
||||
}
|
||||
}
|
||||
|
||||
/// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation.
|
||||
/// Keep this in sync with `Token::can_begin_literal_maybe_minus` excluding unary negation.
|
||||
pub fn from_token(token: &Token) -> Option<Lit> {
|
||||
match token.uninterpolate().kind {
|
||||
Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
|
||||
@ -663,7 +664,7 @@ impl Token {
|
||||
}
|
||||
|
||||
/// Returns `true` if the token is an interpolated path.
|
||||
fn is_path(&self) -> bool {
|
||||
fn is_whole_path(&self) -> bool {
|
||||
if let Interpolated(nt) = &self.kind
|
||||
&& let NtPath(..) = &nt.0
|
||||
{
|
||||
@ -709,7 +710,7 @@ impl Token {
|
||||
pub fn is_path_start(&self) -> bool {
|
||||
self == &ModSep
|
||||
|| self.is_qpath_start()
|
||||
|| self.is_path()
|
||||
|| self.is_whole_path()
|
||||
|| self.is_path_segment_keyword()
|
||||
|| self.is_ident() && !self.is_reserved_ident()
|
||||
}
|
||||
|
@ -28,18 +28,7 @@ use smallvec::{smallvec, SmallVec};
|
||||
use std::borrow::Cow;
|
||||
use std::{cmp, fmt, iter};
|
||||
|
||||
/// When the main Rust parser encounters a syntax-extension invocation, it
|
||||
/// parses the arguments to the invocation as a token tree. This is a very
|
||||
/// loose structure, such that all sorts of different AST fragments can
|
||||
/// be passed to syntax extensions using a uniform type.
|
||||
///
|
||||
/// If the syntax extension is an MBE macro, it will attempt to match its
|
||||
/// LHS token tree against the provided token tree, and if it finds a
|
||||
/// match, will transcribe the RHS token tree, splicing in any captured
|
||||
/// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
|
||||
///
|
||||
/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
|
||||
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
|
||||
/// Part of a `TokenStream`.
|
||||
#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum TokenTree {
|
||||
/// A single token. Should never be `OpenDelim` or `CloseDelim`, because
|
||||
|
@ -480,7 +480,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
|
||||
try_visit!(visitor.visit_path(&use_tree.prefix, id));
|
||||
match use_tree.kind {
|
||||
UseTreeKind::Simple(rename) => {
|
||||
// The extra IDs are handled during HIR lowering.
|
||||
// The extra IDs are handled during AST lowering.
|
||||
visit_opt!(visitor, visit_ident, rename);
|
||||
}
|
||||
UseTreeKind::Glob => {}
|
||||
@ -576,7 +576,10 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
|
||||
try_visit!(visitor.visit_path(path, pattern.id));
|
||||
walk_list!(visitor, visit_pat_field, fields);
|
||||
}
|
||||
PatKind::Box(subpattern) | PatKind::Ref(subpattern, _) | PatKind::Paren(subpattern) => {
|
||||
PatKind::Box(subpattern)
|
||||
| PatKind::Deref(subpattern)
|
||||
| PatKind::Ref(subpattern, _)
|
||||
| PatKind::Paren(subpattern) => {
|
||||
try_visit!(visitor.visit_pat(subpattern));
|
||||
}
|
||||
PatKind::Ident(_, ident, optional_subpattern) => {
|
||||
@ -920,7 +923,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
visit_opt!(visitor, visit_label, opt_label);
|
||||
try_visit!(visitor.visit_block(block));
|
||||
}
|
||||
ExprKind::Match(subexpression, arms) => {
|
||||
ExprKind::Match(subexpression, arms, _kind) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
walk_list!(visitor, visit_arm, arms);
|
||||
}
|
||||
|
@ -29,11 +29,12 @@
|
||||
//! item id (`item_id`) in case of impl trait or path resolution id (`path_id`) otherwise.
|
||||
//!
|
||||
//! Since we do not have a proper way to obtain function type information by path resolution
|
||||
//! in AST, we mark each function parameter type as `InferDelegation` and inherit it in `AstConv`.
|
||||
//! in AST, we mark each function parameter type as `InferDelegation` and inherit it during
|
||||
//! HIR ty lowering.
|
||||
//!
|
||||
//! Similarly generics, predicates and header are set to the "default" values.
|
||||
//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
|
||||
//! also be emitted in `AstConv`.
|
||||
//! also be emitted during HIR ty lowering.
|
||||
|
||||
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
|
||||
|
||||
@ -129,7 +130,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
) -> &'hir hir::FnDecl<'hir> {
|
||||
let args_count = if let Some(local_sig_id) = sig_id.as_local() {
|
||||
// Map may be filled incorrectly due to recursive delegation.
|
||||
// Error will be emmited later in astconv.
|
||||
// Error will be emitted later during HIR ty lowering.
|
||||
self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
|
||||
} else {
|
||||
self.tcx.fn_arg_names(sig_id).len()
|
||||
|
@ -157,7 +157,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
hir::ExprKind::AddrOf(*k, *m, ohs)
|
||||
}
|
||||
ExprKind::Let(pat, scrutinee, span, is_recovered) => {
|
||||
hir::ExprKind::Let(self.arena.alloc(hir::Let {
|
||||
hir::ExprKind::Let(self.arena.alloc(hir::LetExpr {
|
||||
span: self.lower_span(*span),
|
||||
pat: self.lower_pat(pat),
|
||||
ty: None,
|
||||
@ -181,10 +181,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
)
|
||||
}),
|
||||
ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
|
||||
ExprKind::Match(expr, arms) => hir::ExprKind::Match(
|
||||
ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(
|
||||
self.lower_expr(expr),
|
||||
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
||||
hir::MatchSource::Normal,
|
||||
match kind {
|
||||
MatchKind::Prefix => hir::MatchSource::Normal,
|
||||
MatchKind::Postfix => hir::MatchSource::Postfix,
|
||||
},
|
||||
),
|
||||
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
||||
ExprKind::Closure(box Closure {
|
||||
|
@ -55,7 +55,7 @@ pub(super) fn index_hir<'hir>(
|
||||
OwnerNode::TraitItem(item) => collector.visit_trait_item(item),
|
||||
OwnerNode::ImplItem(item) => collector.visit_impl_item(item),
|
||||
OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item),
|
||||
OwnerNode::AssocOpaqueTy(..) => unreachable!(),
|
||||
OwnerNode::Synthetic => unreachable!(),
|
||||
};
|
||||
|
||||
for (local_id, node) in collector.nodes.iter_enumerated() {
|
||||
|
@ -1427,8 +1427,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
|
||||
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
|
||||
// these into hir when we lower thee where clauses), but this makes it quite difficult to
|
||||
// keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
|
||||
// where clauses for `?Sized`.
|
||||
// keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
|
||||
// checks both param bounds and where clauses for `?Sized`.
|
||||
for pred in &generics.where_clause.predicates {
|
||||
let WherePredicate::BoundPredicate(bound_pred) = pred else {
|
||||
continue;
|
||||
|
@ -55,7 +55,9 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxt, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate};
|
||||
use rustc_hir::{
|
||||
ConstArg, GenericArg, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
|
||||
};
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::span_bug;
|
||||
@ -797,7 +799,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
LifetimeRes::Param { .. } => {
|
||||
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
|
||||
}
|
||||
LifetimeRes::Fresh { param, .. } => {
|
||||
LifetimeRes::Fresh { param, kind, .. } => {
|
||||
// Late resolution delegates to us the creation of the `LocalDefId`.
|
||||
let _def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
@ -808,7 +810,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
);
|
||||
debug!(?_def_id);
|
||||
|
||||
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided)
|
||||
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind))
|
||||
}
|
||||
LifetimeRes::Static | LifetimeRes::Error => return None,
|
||||
res => panic!(
|
||||
@ -1605,13 +1607,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
for lifetime in captured_lifetimes_to_duplicate {
|
||||
let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error);
|
||||
let old_def_id = match res {
|
||||
LifetimeRes::Param { param: old_def_id, binder: _ } => old_def_id,
|
||||
let (old_def_id, missing_kind) = match res {
|
||||
LifetimeRes::Param { param: old_def_id, binder: _ } => (old_def_id, None),
|
||||
|
||||
LifetimeRes::Fresh { param, binder: _ } => {
|
||||
LifetimeRes::Fresh { param, kind, .. } => {
|
||||
debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
|
||||
if let Some(old_def_id) = self.orig_opt_local_def_id(param) {
|
||||
old_def_id
|
||||
(old_def_id, Some(kind))
|
||||
} else {
|
||||
self.dcx()
|
||||
.span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime");
|
||||
@ -1651,6 +1653,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
duplicated_lifetime_node_id,
|
||||
duplicated_lifetime_def_id,
|
||||
self.lower_ident(lifetime.ident),
|
||||
missing_kind,
|
||||
));
|
||||
|
||||
// Now make an arg that we can use for the generic params of the opaque tykind.
|
||||
@ -1668,27 +1671,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let bounds = this
|
||||
.with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
|
||||
|
||||
let generic_params = this.arena.alloc_from_iter(
|
||||
synthesized_lifetime_definitions.iter().map(|&(new_node_id, new_def_id, ident)| {
|
||||
let hir_id = this.lower_node_id(new_node_id);
|
||||
let (name, kind) = if ident.name == kw::UnderscoreLifetime {
|
||||
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided)
|
||||
} else {
|
||||
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
|
||||
};
|
||||
let generic_params =
|
||||
this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
|
||||
|&(new_node_id, new_def_id, ident, missing_kind)| {
|
||||
let hir_id = this.lower_node_id(new_node_id);
|
||||
let (name, kind) = if ident.name == kw::UnderscoreLifetime {
|
||||
(
|
||||
hir::ParamName::Fresh,
|
||||
hir::LifetimeParamKind::Elided(
|
||||
missing_kind.unwrap_or(MissingLifetimeKind::Underscore),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
|
||||
};
|
||||
|
||||
hir::GenericParam {
|
||||
hir_id,
|
||||
def_id: new_def_id,
|
||||
name,
|
||||
span: ident.span,
|
||||
pure_wrt_drop: false,
|
||||
kind: hir::GenericParamKind::Lifetime { kind },
|
||||
colon_span: None,
|
||||
source: hir::GenericParamSource::Generics,
|
||||
}
|
||||
}),
|
||||
);
|
||||
hir::GenericParam {
|
||||
hir_id,
|
||||
def_id: new_def_id,
|
||||
name,
|
||||
span: ident.span,
|
||||
pure_wrt_drop: false,
|
||||
kind: hir::GenericParamKind::Lifetime { kind },
|
||||
colon_span: None,
|
||||
source: hir::GenericParamSource::Generics,
|
||||
}
|
||||
},
|
||||
));
|
||||
debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
|
||||
|
||||
let lifetime_mapping = self.arena.alloc_slice(&synthesized_lifetime_args);
|
||||
|
@ -91,6 +91,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
PatKind::Box(inner) => {
|
||||
break hir::PatKind::Box(self.lower_pat(inner));
|
||||
}
|
||||
PatKind::Deref(inner) => {
|
||||
break hir::PatKind::Deref(self.lower_pat(inner));
|
||||
}
|
||||
PatKind::Ref(inner, mutbl) => {
|
||||
break hir::PatKind::Ref(self.lower_pat(inner), *mutbl);
|
||||
}
|
||||
|
@ -564,6 +564,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
gate_all!(generic_const_items, "generic const items are experimental");
|
||||
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
|
||||
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||
gate_all!(postfix_match, "postfix match is experimental");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
@ -607,13 +608,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
};
|
||||
}
|
||||
|
||||
gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
|
||||
// Despite being a new feature, `where T: Trait<Assoc(): Sized>`, which is RTN syntax now,
|
||||
// used to be gated under associated_type_bounds, which are right above, so RTN needs to
|
||||
// be too.
|
||||
gate_all_legacy_dont_use!(return_type_notation, "return type notation is experimental");
|
||||
gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
|
||||
gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all_legacy_dont_use!(
|
||||
exclusive_range_pattern,
|
||||
"exclusive range pattern syntax is experimental"
|
||||
|
@ -1626,6 +1626,12 @@ impl<'a> State<'a> {
|
||||
self.word("box ");
|
||||
self.print_pat(inner);
|
||||
}
|
||||
PatKind::Deref(inner) => {
|
||||
self.word("deref!");
|
||||
self.popen();
|
||||
self.print_pat(inner);
|
||||
self.pclose();
|
||||
}
|
||||
PatKind::Ref(inner, mutbl) => {
|
||||
self.word("&");
|
||||
if mutbl.is_mut() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::pp::Breaks::Inconsistent;
|
||||
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
||||
use ast::ForLoopKind;
|
||||
use ast::{ForLoopKind, MatchKind};
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
@ -589,12 +589,22 @@ impl<'a> State<'a> {
|
||||
self.word_nbsp("loop");
|
||||
self.print_block_with_attrs(blk, attrs);
|
||||
}
|
||||
ast::ExprKind::Match(expr, arms) => {
|
||||
ast::ExprKind::Match(expr, arms, match_kind) => {
|
||||
self.cbox(0);
|
||||
self.ibox(0);
|
||||
self.word_nbsp("match");
|
||||
self.print_expr_as_cond(expr);
|
||||
self.space();
|
||||
|
||||
match match_kind {
|
||||
MatchKind::Prefix => {
|
||||
self.word_nbsp("match");
|
||||
self.print_expr_as_cond(expr);
|
||||
self.space();
|
||||
}
|
||||
MatchKind::Postfix => {
|
||||
self.print_expr_as_cond(expr);
|
||||
self.word_nbsp(".match");
|
||||
}
|
||||
}
|
||||
|
||||
self.bopen();
|
||||
self.print_inner_attributes_no_trailing_hardbreak(attrs);
|
||||
for arm in arms {
|
||||
|
@ -132,6 +132,12 @@ borrowck_moved_due_to_usage_in_operator =
|
||||
*[false] operator
|
||||
}
|
||||
|
||||
borrowck_opaque_type_lifetime_mismatch =
|
||||
opaque type used twice with different lifetimes
|
||||
.label = lifetime `{$arg}` used here
|
||||
.prev_lifetime_label = lifetime `{$prev}` previously used here
|
||||
.note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
|
||||
borrowck_opaque_type_non_generic_param =
|
||||
expected generic {$kind} parameter, found `{$ty}`
|
||||
.label = {STREQ($ty, "'static") ->
|
||||
|
@ -716,7 +716,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
.copied()
|
||||
.find_map(find_fn_kind_from_did),
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.explicit_item_super_predicates(def_id)
|
||||
.iter_instantiated_copied(tcx, args)
|
||||
.find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
|
||||
ty::Closure(_, args) => match args.as_closure().kind() {
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use core::ops::ControlFlow;
|
||||
use hir::ExprKind;
|
||||
use hir::{ExprKind, Param};
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
@ -725,25 +725,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
_ => local_decl.source_info.span,
|
||||
};
|
||||
|
||||
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 body = self.infcx.tcx.hir().body(body_id);
|
||||
BindingFinder { span: pat_span }.visit_body(body).break_value()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// With ref-binding patterns, the mutability suggestion has to apply to
|
||||
// the binding, not the reference (which would be a type error):
|
||||
//
|
||||
// `let &b = a;` -> `let &(mut b) = a;`
|
||||
if let Some(hir_id) = hir_id
|
||||
// or
|
||||
// `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 node = self.infcx.tcx.hir_node(hir_id)
|
||||
&& let hir::Node::Local(hir::Local {
|
||||
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
|
||||
..
|
||||
}) = self.infcx.tcx.hir_node(hir_id)
|
||||
})
|
||||
| hir::Node::Param(Param {
|
||||
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
|
||||
..
|
||||
}) = node
|
||||
&& let Ok(name) =
|
||||
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
|
||||
{
|
||||
@ -1310,6 +1311,16 @@ impl<'tcx> Visitor<'tcx> for BindingFinder {
|
||||
hir::intravisit::walk_stmt(self, s)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result {
|
||||
if let hir::Pat { kind: hir::PatKind::Ref(_, _), span, .. } = param.pat
|
||||
&& *span == self.span
|
||||
{
|
||||
ControlFlow::Break(param.hir_id)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
|
||||
|
@ -9,17 +9,77 @@ use rustc_infer::traits::{Obligation, ObligationCause};
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::traits::DefiningAnchor;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::RegionVid;
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgs};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
|
||||
use crate::session_diagnostics::NonGenericOpaqueTypeParam;
|
||||
|
||||
use super::RegionInferenceContext;
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
fn universal_name(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
self.scc_values
|
||||
.universal_regions_outlived_by(scc)
|
||||
.find_map(|lb| self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?))
|
||||
}
|
||||
|
||||
fn generic_arg_to_region(&self, arg: ty::GenericArg<'tcx>) -> Option<RegionVid> {
|
||||
let region = arg.as_region()?;
|
||||
|
||||
if let ty::RePlaceholder(..) = region.kind() {
|
||||
None
|
||||
} else {
|
||||
Some(self.to_region_vid(region))
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that all opaque types have the same region parameters if they have the same
|
||||
/// non-region parameters. This is necessary because within the new solver we perform various query operations
|
||||
/// modulo regions, and thus could unsoundly select some impls that don't hold.
|
||||
fn check_unique(
|
||||
&self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: &FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) {
|
||||
for (i, (a, a_ty)) in opaque_ty_decls.iter().enumerate() {
|
||||
for (b, b_ty) in opaque_ty_decls.iter().skip(i + 1) {
|
||||
if a.def_id != b.def_id {
|
||||
continue;
|
||||
}
|
||||
// Non-lifetime params differ -> ok
|
||||
if infcx.tcx.erase_regions(a.args) != infcx.tcx.erase_regions(b.args) {
|
||||
continue;
|
||||
}
|
||||
trace!(?a, ?b);
|
||||
for (a, b) in a.args.iter().zip(b.args) {
|
||||
trace!(?a, ?b);
|
||||
let Some(r1) = self.generic_arg_to_region(a) else {
|
||||
continue;
|
||||
};
|
||||
let Some(r2) = self.generic_arg_to_region(b) else {
|
||||
continue;
|
||||
};
|
||||
if self.eval_equal(r1, r2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
|
||||
arg: self.universal_name(r1).unwrap().into(),
|
||||
prev: self.universal_name(r2).unwrap().into(),
|
||||
span: a_ty.span,
|
||||
prev_span: b_ty.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve any opaque types that were encountered while borrow checking
|
||||
/// this item. This is then used to get the type in the `type_of` query.
|
||||
///
|
||||
@ -65,6 +125,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
|
||||
self.check_unique(infcx, &opaque_ty_decls);
|
||||
|
||||
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
|
||||
|
||||
let member_constraints: FxIndexMap<_, _> = self
|
||||
@ -80,26 +142,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
let mut arg_regions = vec![self.universal_regions.fr_static];
|
||||
|
||||
let to_universal_region = |vid, arg_regions: &mut Vec<_>| {
|
||||
trace!(?vid);
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
trace!(?scc);
|
||||
match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| {
|
||||
self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?)
|
||||
}) {
|
||||
Some(region) => {
|
||||
let vid = self.universal_regions.to_region_vid(region);
|
||||
arg_regions.push(vid);
|
||||
region
|
||||
}
|
||||
None => {
|
||||
arg_regions.push(vid);
|
||||
ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
"opaque type with non-universal region args",
|
||||
)
|
||||
}
|
||||
let to_universal_region = |vid, arg_regions: &mut Vec<_>| match self.universal_name(vid)
|
||||
{
|
||||
Some(region) => {
|
||||
let vid = self.universal_regions.to_region_vid(region);
|
||||
arg_regions.push(vid);
|
||||
region
|
||||
}
|
||||
None => {
|
||||
arg_regions.push(vid);
|
||||
ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
"opaque type with non-universal region args",
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@ -136,6 +192,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
|
||||
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
|
||||
.unwrap_or(infcx.tcx.lifetimes.re_erased),
|
||||
ty::RePlaceholder(_) => ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
"hidden type contains placeholders, we don't support higher kinded opaques yet",
|
||||
),
|
||||
_ => region,
|
||||
});
|
||||
debug!(?universal_concrete_type);
|
||||
@ -378,10 +439,6 @@ fn check_opaque_type_parameter_valid(
|
||||
// Only check the parent generics, which will ignore any of the
|
||||
// duplicated lifetime args that come from reifying late-bounds.
|
||||
for (i, arg) in opaque_type_key.args.iter().take(parent_generics.count()).enumerate() {
|
||||
if let Err(guar) = arg.error_reported() {
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) if is_ty_alias => {
|
||||
|
@ -304,6 +304,19 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
|
||||
pub param_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck_opaque_type_lifetime_mismatch)]
|
||||
pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> {
|
||||
pub arg: GenericArg<'tcx>,
|
||||
pub prev: GenericArg<'tcx>,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[note]
|
||||
pub span: Span,
|
||||
#[label(borrowck_prev_lifetime_label)]
|
||||
pub prev_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureReasonLabel<'a> {
|
||||
#[label(borrowck_moved_due_to_call)]
|
||||
|
@ -61,7 +61,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
pub(super) fn instantiate_canonical_with_fresh_inference_vars<T>(
|
||||
pub(super) fn instantiate_canonical<T>(
|
||||
&mut self,
|
||||
span: Span,
|
||||
canonical: &Canonical<'tcx, T>,
|
||||
@ -69,8 +69,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let (instantiated, _) =
|
||||
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
|
||||
let (instantiated, _) = self.infcx.instantiate_canonical(span, canonical);
|
||||
instantiated
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// (e.g., the `_` in the code above) with fresh variables.
|
||||
// Then replace the bound items in the fn sig with fresh variables,
|
||||
// so that they represent the view from "inside" the closure.
|
||||
let user_provided_sig = self
|
||||
.instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig);
|
||||
let user_provided_sig = self.instantiate_canonical(body.span, &user_provided_poly_sig);
|
||||
let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars(
|
||||
body.span,
|
||||
BoundRegionConversionTime::FnCall,
|
||||
@ -88,7 +87,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
self.tcx(),
|
||||
ty::CoroutineArgsParts {
|
||||
parent_args: args.parent_args(),
|
||||
kind_ty: Ty::from_closure_kind(self.tcx(), args.kind()),
|
||||
kind_ty: Ty::from_coroutine_closure_kind(self.tcx(), args.kind()),
|
||||
return_ty: user_provided_sig.output(),
|
||||
tupled_upvars_ty,
|
||||
// For async closures, none of these can be annotated, so just fill
|
||||
|
@ -1109,7 +1109,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let tcx = self.tcx();
|
||||
for user_annotation in self.user_type_annotations {
|
||||
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
|
||||
let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
|
||||
let annotation = self.instantiate_canonical(span, user_ty);
|
||||
if let ty::UserType::TypeOf(def, args) = annotation
|
||||
&& let DefKind::InlineConst = tcx.def_kind(def)
|
||||
{
|
||||
|
@ -189,7 +189,7 @@ pub fn parse_asm_args<'a>(
|
||||
args.templates.push(template);
|
||||
continue;
|
||||
} else {
|
||||
return p.unexpected();
|
||||
p.unexpected_any()?
|
||||
};
|
||||
|
||||
allow_templates = false;
|
||||
|
@ -151,7 +151,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
|
||||
};
|
||||
|
||||
if parser.token != token::Eof {
|
||||
return parser.unexpected();
|
||||
parser.unexpected()?;
|
||||
}
|
||||
|
||||
Ok(Assert { cond_expr, custom_message })
|
||||
|
@ -245,7 +245,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
ExprKind::Let(_, local_expr, _, _) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
ExprKind::Match(local_expr, _) => {
|
||||
ExprKind::Match(local_expr, ..) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
ExprKind::MethodCall(call) => {
|
||||
|
@ -132,7 +132,7 @@ fn cs_partial_cmp(
|
||||
// Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354
|
||||
|
||||
if !tag_then_data
|
||||
&& let ExprKind::Match(_, arms) = &mut expr1.kind
|
||||
&& let ExprKind::Match(_, arms, _) = &mut expr1.kind
|
||||
&& let Some(last) = arms.last_mut()
|
||||
&& let PatKind::Wild = last.pat.kind
|
||||
{
|
||||
|
@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::path_std;
|
||||
|
||||
use ast::EnumDef;
|
||||
use rustc_ast::{self as ast, MetaItem};
|
||||
use rustc_ast::{self as ast, EnumDef, MetaItem};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
@ -49,7 +49,6 @@ mod log_syntax;
|
||||
mod source_util;
|
||||
mod test;
|
||||
mod trace_macros;
|
||||
mod type_ascribe;
|
||||
mod util;
|
||||
|
||||
pub mod asm;
|
||||
@ -99,7 +98,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||
std_panic: edition_panic::expand_panic,
|
||||
stringify: source_util::expand_stringify,
|
||||
trace_macros: trace_macros::expand_trace_macros,
|
||||
type_ascribe: type_ascribe::expand_type_ascribe,
|
||||
unreachable: edition_panic::expand_unreachable,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{token, Expr, ExprKind, Ty};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub fn expand_type_ascribe(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
span: Span,
|
||||
tts: TokenStream,
|
||||
) -> MacroExpanderResult<'static> {
|
||||
let (expr, ty) = match parse_ascribe(cx, tts) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(err) => {
|
||||
let guar = err.emit();
|
||||
return ExpandResult::Ready(DummyResult::any(span, guar));
|
||||
}
|
||||
};
|
||||
|
||||
let asc_expr = cx.expr(span, ExprKind::Type(expr, ty));
|
||||
|
||||
ExpandResult::Ready(MacEager::expr(asc_expr))
|
||||
}
|
||||
|
||||
fn parse_ascribe<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Expr>, P<Ty>)> {
|
||||
let mut parser = cx.new_parser_from_tts(stream);
|
||||
|
||||
let expr = parser.parse_expr()?;
|
||||
parser.expect(&token::Comma)?;
|
||||
|
||||
let ty = parser.parse_ty()?;
|
||||
|
||||
Ok((expr, ty))
|
||||
}
|
@ -757,13 +757,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::ptr_guaranteed_cmp => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
|
||||
let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b).load_scalar(fx);
|
||||
ret.write_cvalue(fx, CValue::by_val(val, fx.layout_of(fx.tcx.types.u8)));
|
||||
}
|
||||
|
||||
sym::caller_location => {
|
||||
intrinsic_args!(fx, args => (); intrinsic);
|
||||
|
||||
|
@ -315,6 +315,7 @@ pub unsafe fn create_module<'ll>(
|
||||
//
|
||||
// On the wasm targets it will get hooked up to the "producer" sections
|
||||
// `processed-by` information.
|
||||
#[allow(clippy::option_env_unwrap)]
|
||||
let rustc_producer =
|
||||
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
|
||||
let name_metadata = llvm::LLVMMDStringInContext(
|
||||
|
@ -85,14 +85,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
|
||||
let bx = self;
|
||||
|
||||
match coverage.kind {
|
||||
// Marker statements have no effect during codegen,
|
||||
// so return early and don't create `func_coverage`.
|
||||
CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => return,
|
||||
// Match exhaustively to ensure that newly-added kinds are classified correctly.
|
||||
CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. } => {}
|
||||
}
|
||||
|
||||
let Some(function_coverage_info) =
|
||||
bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref()
|
||||
else {
|
||||
@ -109,7 +101,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
let Coverage { kind } = coverage;
|
||||
match *kind {
|
||||
CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!(
|
||||
"unexpected marker statement {kind:?} should have caused an early return"
|
||||
"marker statement {kind:?} should have been removed by CleanupPostBorrowck"
|
||||
),
|
||||
CoverageKind::CounterIncrement { id } => {
|
||||
func_coverage.mark_counter_id_seen(id);
|
||||
|
@ -100,12 +100,6 @@ impl Command {
|
||||
Program::Lld(ref p, flavor) => {
|
||||
let mut c = process::Command::new(p);
|
||||
c.arg("-flavor").arg(flavor.as_str());
|
||||
if let LldFlavor::Wasm = flavor {
|
||||
// LLVM expects host-specific formatting for @file
|
||||
// arguments, but we always generate posix formatted files
|
||||
// at this time. Indicate as such.
|
||||
c.arg("--rsp-quoting=posix");
|
||||
}
|
||||
c
|
||||
}
|
||||
};
|
||||
|
@ -785,7 +785,7 @@ fn link_natively<'a>(
|
||||
let mut i = 0;
|
||||
loop {
|
||||
i += 1;
|
||||
prog = sess.time("run_linker", || exec_linker(sess, &cmd, out_filename, tmpdir));
|
||||
prog = sess.time("run_linker", || exec_linker(sess, &cmd, out_filename, flavor, tmpdir));
|
||||
let Ok(ref output) = prog else {
|
||||
break;
|
||||
};
|
||||
@ -1576,6 +1576,7 @@ fn exec_linker(
|
||||
sess: &Session,
|
||||
cmd: &Command,
|
||||
out_filename: &Path,
|
||||
flavor: LinkerFlavor,
|
||||
tmpdir: &Path,
|
||||
) -> io::Result<Output> {
|
||||
// When attempting to spawn the linker we run a risk of blowing out the
|
||||
@ -1584,9 +1585,9 @@ fn exec_linker(
|
||||
//
|
||||
// Here we attempt to handle errors from the OS saying "your list of
|
||||
// arguments is too big" by reinvoking the linker again with an `@`-file
|
||||
// that contains all the arguments. The theory is that this is then
|
||||
// accepted on all linkers and the linker will read all its options out of
|
||||
// there instead of looking at the command line.
|
||||
// that contains all the arguments (aka 'response' files).
|
||||
// The theory is that this is then accepted on all linkers and the linker
|
||||
// will read all its options out of there instead of looking at the command line.
|
||||
if !cmd.very_likely_to_exceed_some_spawn_limit() {
|
||||
match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
|
||||
Ok(child) => {
|
||||
@ -1606,8 +1607,12 @@ fn exec_linker(
|
||||
let mut args = String::new();
|
||||
for arg in cmd2.take_args() {
|
||||
args.push_str(
|
||||
&Escape { arg: arg.to_str().unwrap(), is_like_msvc: sess.target.is_like_msvc }
|
||||
.to_string(),
|
||||
&Escape {
|
||||
arg: arg.to_str().unwrap(),
|
||||
// LLD also uses MSVC-like parsing for @-files by default when running on windows hosts
|
||||
is_like_msvc: sess.target.is_like_msvc || (cfg!(windows) && flavor.uses_lld()),
|
||||
}
|
||||
.to_string(),
|
||||
);
|
||||
args.push('\n');
|
||||
}
|
||||
|
@ -81,10 +81,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
return library.kind.is_statically_included().then_some(def_id);
|
||||
}
|
||||
|
||||
if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Only consider nodes that actually have exported symbols.
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Fn | DefKind::Static { .. } => {}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::place::PlaceRef;
|
||||
use super::FunctionCx;
|
||||
use crate::common::IntPredicate;
|
||||
use crate::errors;
|
||||
use crate::errors::InvalidMonomorphization;
|
||||
use crate::meth;
|
||||
@ -456,12 +455,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
sym::ptr_guaranteed_cmp => {
|
||||
let a = args[0].immediate();
|
||||
let b = args[1].immediate();
|
||||
bx.icmp(IntPredicate::IntEQ, a, b)
|
||||
}
|
||||
|
||||
sym::ptr_offset_from | sym::ptr_offset_from_unsigned => {
|
||||
let ty = fn_args.type_at(0);
|
||||
let pointee_size = bx.layout_of(ty).size;
|
||||
|
@ -2,6 +2,7 @@ use crate::base;
|
||||
use crate::common;
|
||||
use crate::traits::*;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||
use rustc_middle::ty;
|
||||
@ -40,23 +41,34 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
||||
.iter()
|
||||
.map(|(op, op_sp)| match *op {
|
||||
hir::InlineAsmOperand::Const { ref anon_const } => {
|
||||
let const_value = cx
|
||||
.tcx()
|
||||
.const_eval_poly(anon_const.def_id.to_def_id())
|
||||
.unwrap_or_else(|_| {
|
||||
span_bug!(*op_sp, "asm const cannot be resolved")
|
||||
});
|
||||
let ty = cx
|
||||
.tcx()
|
||||
.typeck_body(anon_const.body)
|
||||
.node_type(anon_const.hir_id);
|
||||
let string = common::asm_const_to_str(
|
||||
cx.tcx(),
|
||||
*op_sp,
|
||||
const_value,
|
||||
cx.layout_of(ty),
|
||||
);
|
||||
GlobalAsmOperandRef::Const { string }
|
||||
match cx.tcx().const_eval_poly(anon_const.def_id.to_def_id()) {
|
||||
Ok(const_value) => {
|
||||
let ty = cx
|
||||
.tcx()
|
||||
.typeck_body(anon_const.body)
|
||||
.node_type(anon_const.hir_id);
|
||||
let string = common::asm_const_to_str(
|
||||
cx.tcx(),
|
||||
*op_sp,
|
||||
const_value,
|
||||
cx.layout_of(ty),
|
||||
);
|
||||
GlobalAsmOperandRef::Const { string }
|
||||
}
|
||||
Err(ErrorHandled::Reported { .. }) => {
|
||||
// An error has already been reported and
|
||||
// compilation is guaranteed to fail if execution
|
||||
// hits this path. So an empty string instead of
|
||||
// a stringified constant value will suffice.
|
||||
GlobalAsmOperandRef::Const { string: String::new() }
|
||||
}
|
||||
Err(ErrorHandled::TooGeneric(_)) => {
|
||||
span_bug!(
|
||||
*op_sp,
|
||||
"asm const cannot be resolved; too generic"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { ref anon_const } => {
|
||||
let ty = cx
|
||||
|
@ -21,7 +21,6 @@ use rustc_session::{
|
||||
};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::spec::Target;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@ -70,12 +69,6 @@ pub trait CodegenBackend {
|
||||
fn print_passes(&self) {}
|
||||
fn print_version(&self) {}
|
||||
|
||||
/// If this plugin provides additional builtin targets, provide the one enabled by the options here.
|
||||
/// Be careful: this is called *before* init() is called.
|
||||
fn target_override(&self, _opts: &config::Options) -> Option<Target> {
|
||||
None
|
||||
}
|
||||
|
||||
/// The metadata loader used to load rlib and dylib metadata.
|
||||
///
|
||||
/// Alternative codegen backends may want to use different rlib or dylib formats than the
|
||||
|
@ -1034,8 +1034,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("{:?} is now live", local);
|
||||
|
||||
// We avoid `ty.is_trivially_sized` since that (a) cannot assume WF, so it recurses through
|
||||
// all fields of a tuple, and (b) does something expensive for ADTs.
|
||||
// We avoid `ty.is_trivially_sized` since that does something expensive for ADTs.
|
||||
fn is_very_trivially_sized(ty: Ty<'_>) -> bool {
|
||||
match ty.kind() {
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
@ -1054,9 +1053,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Never
|
||||
| ty::Error(_) => true,
|
||||
| ty::Error(_)
|
||||
| ty::Dynamic(_, _, ty::DynStar) => true,
|
||||
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => false,
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
|
||||
|
||||
ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)),
|
||||
|
||||
|
@ -111,6 +111,8 @@ fn intern_as_new_static<'tcx>(
|
||||
feed.generics_of(tcx.generics_of(static_id).clone());
|
||||
feed.def_ident_span(tcx.def_ident_span(static_id));
|
||||
feed.explicit_predicates_of(tcx.explicit_predicates_of(static_id));
|
||||
|
||||
feed.feed_hir()
|
||||
}
|
||||
|
||||
/// How a constant value should be interned.
|
||||
@ -291,7 +293,9 @@ pub fn intern_const_alloc_for_constprop<
|
||||
return Ok(());
|
||||
}
|
||||
// Move allocation to `tcx`.
|
||||
for _ in intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))? {
|
||||
if let Some(_) =
|
||||
(intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))?).next()
|
||||
{
|
||||
// We are not doing recursive interning, so we don't currently support provenance.
|
||||
// (If this assertion ever triggers, we should just implement a
|
||||
// proper recursive interning loop -- or just call `intern_const_alloc_recursive`.
|
||||
|
@ -1159,11 +1159,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
};
|
||||
|
||||
// Side-step AllocRef and directly access the underlying bytes more efficiently.
|
||||
// (We are staying inside the bounds here so all is good.)
|
||||
// (We are staying inside the bounds here and all bytes do get overwritten so all is good.)
|
||||
let alloc_id = alloc_ref.alloc_id;
|
||||
let bytes = alloc_ref
|
||||
.alloc
|
||||
.get_bytes_mut(&alloc_ref.tcx, alloc_ref.range)
|
||||
.get_bytes_unchecked_for_overwrite(&alloc_ref.tcx, alloc_ref.range)
|
||||
.map_err(move |e| e.to_interp_error(alloc_id))?;
|
||||
// `zip` would stop when the first iterator ends; we want to definitely
|
||||
// cover all of `bytes`.
|
||||
@ -1184,6 +1184,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
self.mem_copy_repeatedly(src, dest, size, 1, nonoverlapping)
|
||||
}
|
||||
|
||||
/// Performs `num_copies` many copies of `size` many bytes from `src` to `dest + i*size` (where
|
||||
/// `i` is the index of the copy).
|
||||
///
|
||||
/// Either `nonoverlapping` must be true or `num_copies` must be 1; doing repeated copies that
|
||||
/// may overlap is not supported.
|
||||
pub fn mem_copy_repeatedly(
|
||||
&mut self,
|
||||
src: Pointer<Option<M::Provenance>>,
|
||||
@ -1245,8 +1250,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
(dest_alloc_id, dest_prov),
|
||||
dest_range,
|
||||
)?;
|
||||
// Yes we do overwrite all bytes in `dest_bytes`.
|
||||
let dest_bytes = dest_alloc
|
||||
.get_bytes_mut_ptr(&tcx, dest_range)
|
||||
.get_bytes_unchecked_for_overwrite_ptr(&tcx, dest_range)
|
||||
.map_err(|e| e.to_interp_error(dest_alloc_id))?
|
||||
.as_mut_ptr();
|
||||
|
||||
@ -1280,6 +1286,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if num_copies > 1 {
|
||||
assert!(nonoverlapping, "multi-copy only supported in non-overlapping mode");
|
||||
}
|
||||
|
||||
let size_in_bytes = size.bytes_usize();
|
||||
// For particularly large arrays (where this is perf-sensitive) it's common that
|
||||
@ -1292,6 +1301,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
} else if src_alloc_id == dest_alloc_id {
|
||||
let mut dest_ptr = dest_bytes;
|
||||
for _ in 0..num_copies {
|
||||
// Here we rely on `src` and `dest` being non-overlapping if there is more than
|
||||
// one copy.
|
||||
ptr::copy(src_bytes, dest_ptr, size_in_bytes);
|
||||
dest_ptr = dest_ptr.add(size_in_bytes);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_infer::traits::Reveal;
|
||||
use rustc_middle::mir::coverage::CoverageKind;
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
@ -345,11 +346,21 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
||||
self.fail(location, format!("explicit `{kind:?}` is forbidden"));
|
||||
}
|
||||
}
|
||||
StatementKind::Coverage(coverage) => {
|
||||
let kind = &coverage.kind;
|
||||
if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup)
|
||||
&& let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind
|
||||
{
|
||||
self.fail(
|
||||
location,
|
||||
format!("{kind:?} should have been removed after analysis"),
|
||||
);
|
||||
}
|
||||
}
|
||||
StatementKind::Assign(..)
|
||||
| StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Intrinsic(_)
|
||||
| StatementKind::Coverage(_)
|
||||
| StatementKind::ConstEvalCounter
|
||||
| StatementKind::PlaceMention(..)
|
||||
| StatementKind::Nop => {}
|
||||
|
@ -20,6 +20,7 @@
|
||||
//! | ----------------------- | ------------------- | ------------------------------- |
|
||||
//! | `Lrc<T>` | `rc::Rc<T>` | `sync::Arc<T>` |
|
||||
//! |` Weak<T>` | `rc::Weak<T>` | `sync::Weak<T>` |
|
||||
//! | `LRef<'a, T>` [^2] | `&'a mut T` | `&'a T` |
|
||||
//! | | | |
|
||||
//! | `AtomicBool` | `Cell<bool>` | `atomic::AtomicBool` |
|
||||
//! | `AtomicU32` | `Cell<u32>` | `atomic::AtomicU32` |
|
||||
@ -38,7 +39,7 @@
|
||||
//! of a `RefCell`. This is appropriate when interior mutability is not
|
||||
//! required.
|
||||
//!
|
||||
//! [^2] `MTLockRef` is a typedef.
|
||||
//! [^2] `MTRef`, `MTLockRef` are type aliases.
|
||||
|
||||
pub use crate::marker::*;
|
||||
use std::collections::HashMap;
|
||||
@ -208,7 +209,7 @@ cfg_match! {
|
||||
|
||||
use std::cell::RefCell as InnerRwLock;
|
||||
|
||||
pub type MTLockRef<'a, T> = &'a mut MTLock<T>;
|
||||
pub type LRef<'a, T> = &'a mut T;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MTLock<T>(T);
|
||||
@ -274,7 +275,7 @@ cfg_match! {
|
||||
pub use std::sync::Arc as Lrc;
|
||||
pub use std::sync::Weak as Weak;
|
||||
|
||||
pub type MTLockRef<'a, T> = &'a MTLock<T>;
|
||||
pub type LRef<'a, T> = &'a T;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MTLock<T>(Lock<T>);
|
||||
@ -314,6 +315,8 @@ cfg_match! {
|
||||
}
|
||||
}
|
||||
|
||||
pub type MTLockRef<'a, T> = LRef<'a, MTLock<T>>;
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(parallel_compiler, repr(align(64)))]
|
||||
pub struct CacheAligned<T>(pub T);
|
||||
|
@ -189,6 +189,7 @@ mod no_sync {
|
||||
use super::Mode;
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use std::cell::RefMut as LockGuard;
|
||||
|
||||
pub struct Lock<T>(RefCell<T>);
|
||||
|
@ -890,7 +890,7 @@ pub fn version_at_macro_invocation(
|
||||
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
|
||||
let opts = config::Options::default();
|
||||
let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone());
|
||||
let target = config::build_target_config(early_dcx, &opts, None, &sysroot);
|
||||
let target = config::build_target_config(early_dcx, &opts, &sysroot);
|
||||
|
||||
get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_version();
|
||||
}
|
||||
@ -1100,7 +1100,7 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
|
||||
|
||||
let opts = config::Options::default();
|
||||
let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone());
|
||||
let target = config::build_target_config(early_dcx, &opts, None, &sysroot);
|
||||
let target = config::build_target_config(early_dcx, &opts, &sysroot);
|
||||
|
||||
get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_passes();
|
||||
return true;
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Signal handler for rustc
|
||||
//! Primarily used to extract a backtrace from stack overflow
|
||||
|
||||
use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
|
||||
use std::alloc::{alloc, Layout};
|
||||
use std::{fmt, mem, ptr};
|
||||
|
||||
@ -100,7 +101,10 @@ extern "C" fn print_stack_trace(_: libc::c_int) {
|
||||
written += 1;
|
||||
}
|
||||
raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust");
|
||||
written += 1;
|
||||
// get the current stack size WITHOUT blocking and double it
|
||||
let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
|
||||
raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}");
|
||||
written += 2;
|
||||
if written > 24 {
|
||||
// We probably just scrolled the earlier "we got SIGSEGV" message off the terminal
|
||||
raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal");
|
||||
|
@ -1638,6 +1638,27 @@ impl HumanEmitter {
|
||||
*style,
|
||||
);
|
||||
}
|
||||
if let Some(line) = annotated_file.lines.get(line_idx) {
|
||||
for ann in &line.annotations {
|
||||
if let AnnotationType::MultilineStart(pos) = ann.annotation_type
|
||||
{
|
||||
// In the case where we have elided the entire start of the
|
||||
// multispan because those lines were empty, we still need
|
||||
// to draw the `|`s across the `...`.
|
||||
draw_multiline_line(
|
||||
&mut buffer,
|
||||
last_buffer_line_num,
|
||||
width_offset,
|
||||
pos,
|
||||
if ann.is_primary {
|
||||
Style::UnderlinePrimary
|
||||
} else {
|
||||
Style::UnderlineSecondary
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if line_idx_delta == 2 {
|
||||
let unannotated_line = annotated_file
|
||||
.file
|
||||
@ -1665,6 +1686,24 @@ impl HumanEmitter {
|
||||
*style,
|
||||
);
|
||||
}
|
||||
if let Some(line) = annotated_file.lines.get(line_idx) {
|
||||
for ann in &line.annotations {
|
||||
if let AnnotationType::MultilineStart(pos) = ann.annotation_type
|
||||
{
|
||||
draw_multiline_line(
|
||||
&mut buffer,
|
||||
last_buffer_line_num,
|
||||
width_offset,
|
||||
pos,
|
||||
if ann.is_primary {
|
||||
Style::UnderlinePrimary
|
||||
} else {
|
||||
Style::UnderlineSecondary
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2417,7 +2456,15 @@ impl FileWithAnnotatedLines {
|
||||
// the beginning doesn't have an underline, but the current logic seems to be
|
||||
// working correctly.
|
||||
let middle = min(ann.line_start + 4, ann.line_end);
|
||||
for line in ann.line_start + 1..middle {
|
||||
// We'll show up to 4 lines past the beginning of the multispan start.
|
||||
// We will *not* include the tail of lines that are only whitespace.
|
||||
let until = (ann.line_start..middle)
|
||||
.rev()
|
||||
.filter_map(|line| file.get_line(line - 1).map(|s| (line + 1, s)))
|
||||
.find(|(_, s)| !s.trim().is_empty())
|
||||
.map(|(line, _)| line)
|
||||
.unwrap_or(ann.line_start);
|
||||
for line in ann.line_start + 1..until {
|
||||
// Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
|
||||
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(min_specialization))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(array_windows)]
|
||||
|
@ -33,6 +33,9 @@ expand_duplicate_matcher_binding = duplicate matcher binding
|
||||
expand_expected_comma_in_list =
|
||||
expected token: `,`
|
||||
|
||||
expand_expected_paren_or_brace =
|
||||
expected `(` or `{"{"}`, found `{$token}`
|
||||
|
||||
expand_explain_doc_comment_inner =
|
||||
inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::base::ExtCtxt;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
|
||||
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp};
|
||||
use rustc_ast::{attr, token, util::literal};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
@ -524,7 +524,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
}
|
||||
|
||||
pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
|
||||
self.expr(span, ast::ExprKind::Match(arg, arms))
|
||||
self.expr(span, ast::ExprKind::Match(arg, arms, MatchKind::Prefix))
|
||||
}
|
||||
|
||||
pub fn expr_if(
|
||||
|
@ -448,3 +448,11 @@ pub struct InvalidFragmentSpecifier {
|
||||
pub fragment: Ident,
|
||||
pub help: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand_expected_paren_or_brace)]
|
||||
pub struct ExpectedParenOrBrace<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub token: Cow<'a, str>,
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_span)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(yeet_expr)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
|
@ -392,12 +392,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum NamedMatch {
|
||||
MatchedSeq(Vec<NamedMatch>),
|
||||
|
||||
// A metavar match of type `tt`.
|
||||
MatchedTokenTree(rustc_ast::tokenstream::TokenTree),
|
||||
|
||||
// A metavar match of any type other than `tt`.
|
||||
MatchedNonterminal(Lrc<(Nonterminal, rustc_span::Span)>),
|
||||
MatchedSingle(ParseNtResult<Lrc<(Nonterminal, Span)>>),
|
||||
}
|
||||
|
||||
/// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
|
||||
@ -691,11 +686,11 @@ impl TtParser {
|
||||
}
|
||||
Ok(nt) => nt,
|
||||
};
|
||||
let m = match nt {
|
||||
ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new((nt, span))),
|
||||
ParseNtResult::Tt(tt) => MatchedTokenTree(tt),
|
||||
};
|
||||
mp.push_match(next_metavar, seq_depth, m);
|
||||
mp.push_match(
|
||||
next_metavar,
|
||||
seq_depth,
|
||||
MatchedSingle(nt.map_nt(|nt| (Lrc::new((nt, span))))),
|
||||
);
|
||||
mp.idx += 1;
|
||||
} else {
|
||||
unreachable!()
|
||||
|
@ -5,7 +5,7 @@ use crate::mbe;
|
||||
use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
|
||||
use crate::mbe::macro_check;
|
||||
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser};
|
||||
use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree, MatcherLoc};
|
||||
use crate::mbe::macro_parser::{MatcherLoc, NamedMatch::*};
|
||||
use crate::mbe::transcribe::transcribe;
|
||||
|
||||
use ast::token::IdentIsRaw;
|
||||
@ -22,7 +22,7 @@ use rustc_lint_defs::builtin::{
|
||||
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
||||
};
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_parse::parser::{Parser, Recovery};
|
||||
use rustc_parse::parser::{ParseNtResult, Parser, Recovery};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edition::Edition;
|
||||
@ -479,7 +479,7 @@ pub fn compile_declarative_macro(
|
||||
MatchedSeq(s) => s
|
||||
.iter()
|
||||
.map(|m| {
|
||||
if let MatchedTokenTree(tt) = m {
|
||||
if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
|
||||
let tt = mbe::quoted::parse(
|
||||
&TokenStream::new(vec![tt.clone()]),
|
||||
true,
|
||||
@ -505,7 +505,7 @@ pub fn compile_declarative_macro(
|
||||
MatchedSeq(s) => s
|
||||
.iter()
|
||||
.map(|m| {
|
||||
if let MatchedTokenTree(tt) = m {
|
||||
if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
|
||||
return mbe::quoted::parse(
|
||||
&TokenStream::new(vec![tt.clone()]),
|
||||
false,
|
||||
|
@ -194,9 +194,11 @@ fn parse_tree<'a>(
|
||||
}
|
||||
Delimiter::Parenthesis => {}
|
||||
_ => {
|
||||
let tok = pprust::token_kind_to_string(&token::OpenDelim(delim));
|
||||
let msg = format!("expected `(` or `{{`, found `{tok}`");
|
||||
sess.dcx().span_err(delim_span.entire(), msg);
|
||||
let token = pprust::token_kind_to_string(&token::OpenDelim(delim));
|
||||
sess.dcx().emit_err(errors::ExpectedParenOrBrace {
|
||||
span: delim_span.entire(),
|
||||
token,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,14 @@ use crate::errors::{
|
||||
CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
|
||||
NoSyntaxVarsExprRepeat, VarStillRepeating,
|
||||
};
|
||||
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch};
|
||||
use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
|
||||
use crate::mbe::{self, KleeneOp, MetaVarExpr};
|
||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::Diag;
|
||||
use rustc_errors::{pluralize, PResult};
|
||||
use rustc_errors::{pluralize, Diag, PResult};
|
||||
use rustc_parse::parser::ParseNtResult;
|
||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
||||
use rustc_span::{with_metavar_spans, Span, SyntaxContext};
|
||||
@ -250,26 +250,25 @@ pub(super) fn transcribe<'a>(
|
||||
// the meta-var.
|
||||
let ident = MacroRulesNormalizedIdent::new(original_ident);
|
||||
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
|
||||
match cur_matched {
|
||||
MatchedTokenTree(tt) => {
|
||||
let tt = match cur_matched {
|
||||
MatchedSingle(ParseNtResult::Tt(tt)) => {
|
||||
// `tt`s are emitted into the output stream directly as "raw tokens",
|
||||
// without wrapping them into groups.
|
||||
let tt = maybe_use_metavar_location(cx, &stack, sp, tt, &mut marker);
|
||||
result.push(tt);
|
||||
maybe_use_metavar_location(cx, &stack, sp, tt, &mut marker)
|
||||
}
|
||||
MatchedNonterminal(nt) => {
|
||||
MatchedSingle(ParseNtResult::Nt(nt)) => {
|
||||
// Other variables are emitted into the output stream as groups with
|
||||
// `Delimiter::Invisible` to maintain parsing priorities.
|
||||
// `Interpolated` is currently used for such groups in rustc parser.
|
||||
marker.visit_span(&mut sp);
|
||||
result
|
||||
.push(TokenTree::token_alone(token::Interpolated(nt.clone()), sp));
|
||||
TokenTree::token_alone(token::Interpolated(nt.clone()), sp)
|
||||
}
|
||||
MatchedSeq(..) => {
|
||||
// We were unable to descend far enough. This is an error.
|
||||
return Err(cx.dcx().create_err(VarStillRepeating { span: sp, ident }));
|
||||
}
|
||||
}
|
||||
};
|
||||
result.push(tt)
|
||||
} else {
|
||||
// If we aren't able to match the meta-var, we push it back into the result but
|
||||
// with modified syntax context. (I believe this supports nested macros).
|
||||
@ -424,7 +423,7 @@ fn lookup_cur_matched<'a>(
|
||||
interpolations.get(&ident).map(|mut matched| {
|
||||
for &(idx, _) in repeats {
|
||||
match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => break,
|
||||
MatchedSingle(_) => break,
|
||||
MatchedSeq(ads) => matched = ads.get(idx).unwrap(),
|
||||
}
|
||||
}
|
||||
@ -514,7 +513,7 @@ fn lockstep_iter_size(
|
||||
let name = MacroRulesNormalizedIdent::new(*name);
|
||||
match lookup_cur_matched(name, interpolations, repeats) {
|
||||
Some(matched) => match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
|
||||
MatchedSingle(_) => LockstepIterSize::Unconstrained,
|
||||
MatchedSeq(ads) => LockstepIterSize::Constraint(ads.len(), name),
|
||||
},
|
||||
_ => LockstepIterSize::Unconstrained,
|
||||
@ -557,7 +556,7 @@ fn count_repetitions<'a>(
|
||||
// (or at the top-level of `matched` if no depth is given).
|
||||
fn count<'a>(depth_curr: usize, depth_max: usize, matched: &NamedMatch) -> PResult<'a, usize> {
|
||||
match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => Ok(1),
|
||||
MatchedSingle(_) => Ok(1),
|
||||
MatchedSeq(named_matches) => {
|
||||
if depth_curr == depth_max {
|
||||
Ok(named_matches.len())
|
||||
@ -571,7 +570,7 @@ fn count_repetitions<'a>(
|
||||
/// Maximum depth
|
||||
fn depth(counter: usize, matched: &NamedMatch) -> usize {
|
||||
match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => counter,
|
||||
MatchedSingle(_) => counter,
|
||||
MatchedSeq(named_matches) => {
|
||||
let rslt = counter + 1;
|
||||
if let Some(elem) = named_matches.first() { depth(rslt, elem) } else { rslt }
|
||||
@ -599,7 +598,7 @@ fn count_repetitions<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
if let MatchedTokenTree(_) | MatchedNonterminal(_) = matched {
|
||||
if let MatchedSingle(_) = matched {
|
||||
return Err(cx.dcx().create_err(CountRepetitionMisplaced { span: sp.entire() }));
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ pub(crate) fn parse_external_mod(
|
||||
|
||||
// Ensure file paths are acyclic.
|
||||
if let Some(pos) = module.file_path_stack.iter().position(|p| p == &mp.file_path) {
|
||||
Err(ModError::CircularInclusion(module.file_path_stack[pos..].to_vec()))?;
|
||||
do yeet ModError::CircularInclusion(module.file_path_stack[pos..].to_vec());
|
||||
}
|
||||
|
||||
// Actually parse the external file as a module.
|
||||
|
@ -276,8 +276,7 @@ error: foo
|
||||
|
|
||||
2 | fn foo() {
|
||||
| __________^
|
||||
3 | |
|
||||
4 | |
|
||||
... |
|
||||
5 | | }
|
||||
| |___^ test
|
||||
|
||||
|
@ -87,7 +87,7 @@ declare_features! (
|
||||
/// Enables `#[cfg(panic = "...")]` config key.
|
||||
(accepted, cfg_panic, "1.60.0", Some(77443)),
|
||||
/// Allows `cfg(target_abi = "...")`.
|
||||
(accepted, cfg_target_abi, "CURRENT_RUSTC_VERSION", Some(80970)),
|
||||
(accepted, cfg_target_abi, "1.78.0", Some(80970)),
|
||||
/// Allows `cfg(target_feature = "...")`.
|
||||
(accepted, cfg_target_feature, "1.27.0", Some(29717)),
|
||||
/// Allows `cfg(target_vendor = "...")`.
|
||||
@ -149,7 +149,7 @@ declare_features! (
|
||||
/// Allows the use of destructuring assignments.
|
||||
(accepted, destructuring_assignment, "1.59.0", Some(71126)),
|
||||
/// Allows using the `#[diagnostic]` attribute tool namespace
|
||||
(accepted, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(111996)),
|
||||
(accepted, diagnostic_namespace, "1.78.0", Some(111996)),
|
||||
/// Allows `#[doc(alias = "...")]`.
|
||||
(accepted, doc_alias, "1.48.0", Some(50146)),
|
||||
/// Allows `..` in tuple (struct) patterns.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -124,7 +124,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
|
||||
pub use accepted::ACCEPTED_FEATURES;
|
||||
pub use builtin_attrs::AttributeDuplicates;
|
||||
pub use builtin_attrs::{
|
||||
deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local,
|
||||
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
|
||||
is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute,
|
||||
GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
|
||||
};
|
||||
|
@ -98,7 +98,7 @@ declare_features! (
|
||||
(removed, external_doc, "1.54.0", Some(44732),
|
||||
Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
|
||||
/// Allows using `#[ffi_returns_twice]` on foreign functions.
|
||||
(removed, ffi_returns_twice, "CURRENT_RUSTC_VERSION", Some(58314),
|
||||
(removed, ffi_returns_twice, "1.78.0", Some(58314),
|
||||
Some("being investigated by the ffi-unwind project group")),
|
||||
/// Allows generators to be cloned.
|
||||
(removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")),
|
||||
|
@ -214,7 +214,7 @@ declare_features! (
|
||||
/// Allows using `#[omit_gdb_pretty_printer_section]`.
|
||||
(internal, omit_gdb_pretty_printer_section, "1.5.0", None),
|
||||
/// Set the maximum pattern complexity allowed (not limited by default).
|
||||
(internal, pattern_complexity, "CURRENT_RUSTC_VERSION", None),
|
||||
(internal, pattern_complexity, "1.78.0", None),
|
||||
/// Allows using `#[prelude_import]` on glob `use` items.
|
||||
(internal, prelude_import, "1.2.0", None),
|
||||
/// Used to identify crates that contain the profiler runtime.
|
||||
@ -301,11 +301,11 @@ declare_features! (
|
||||
(unstable, csky_target_feature, "1.73.0", Some(44839)),
|
||||
(unstable, ermsb_target_feature, "1.49.0", Some(44839)),
|
||||
(unstable, hexagon_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, lahfsahf_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
|
||||
(unstable, lahfsahf_target_feature, "1.78.0", Some(44839)),
|
||||
(unstable, loongarch_target_feature, "1.73.0", Some(44839)),
|
||||
(unstable, mips_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, powerpc_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, prfchw_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
|
||||
(unstable, prfchw_target_feature, "1.78.0", Some(44839)),
|
||||
(unstable, riscv_target_feature, "1.45.0", Some(44839)),
|
||||
(unstable, rtm_target_feature, "1.35.0", Some(44839)),
|
||||
(unstable, sse4a_target_feature, "1.27.0", Some(44839)),
|
||||
@ -346,7 +346,7 @@ declare_features! (
|
||||
/// Enables experimental inline assembly support for additional architectures.
|
||||
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
|
||||
/// Allows using `label` operands in inline assembly.
|
||||
(unstable, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)),
|
||||
(unstable, asm_goto, "1.78.0", Some(119364)),
|
||||
/// Allows the `may_unwind` option in inline assembly.
|
||||
(unstable, asm_unwind, "1.58.0", Some(93334)),
|
||||
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
|
||||
@ -410,7 +410,7 @@ declare_features! (
|
||||
/// Allows references to types with interior mutability within constants
|
||||
(unstable, const_refs_to_cell, "1.51.0", Some(80384)),
|
||||
/// Allows creating pointers and references to `static` items in constants.
|
||||
(unstable, const_refs_to_static, "CURRENT_RUSTC_VERSION", Some(119618)),
|
||||
(unstable, const_refs_to_static, "1.78.0", Some(119618)),
|
||||
/// Allows `impl const Trait for T` syntax.
|
||||
(unstable, const_trait_impl, "1.42.0", Some(67792)),
|
||||
/// Allows the `?` operator in const contexts.
|
||||
@ -436,6 +436,8 @@ declare_features! (
|
||||
(unstable, deprecated_safe, "1.61.0", Some(94978)),
|
||||
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
|
||||
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
|
||||
/// Allows deref patterns.
|
||||
(incomplete, deref_patterns, "CURRENT_RUSTC_VERSION", Some(87121)),
|
||||
/// Controls errors in trait implementations.
|
||||
(unstable, do_not_recommend, "1.67.0", Some(51992)),
|
||||
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
|
||||
@ -462,9 +464,9 @@ declare_features! (
|
||||
/// Allows defining `extern type`s.
|
||||
(unstable, extern_types, "1.23.0", Some(43467)),
|
||||
/// Allow using 128-bit (quad precision) floating point numbers.
|
||||
(unstable, f128, "CURRENT_RUSTC_VERSION", Some(116909)),
|
||||
(unstable, f128, "1.78.0", Some(116909)),
|
||||
/// Allow using 16-bit (half precision) floating point numbers.
|
||||
(unstable, f16, "CURRENT_RUSTC_VERSION", Some(116909)),
|
||||
(unstable, f16, "1.78.0", Some(116909)),
|
||||
/// Allows the use of `#[ffi_const]` on foreign functions.
|
||||
(unstable, ffi_const, "1.45.0", Some(58328)),
|
||||
/// Allows the use of `#[ffi_pure]` on foreign functions.
|
||||
@ -474,7 +476,7 @@ declare_features! (
|
||||
/// Support delegating implementation of functions to other already implemented functions.
|
||||
(incomplete, fn_delegation, "1.76.0", Some(118212)),
|
||||
/// Allows impls for the Freeze trait.
|
||||
(internal, freeze_impls, "CURRENT_RUSTC_VERSION", Some(121675)),
|
||||
(internal, freeze_impls, "1.78.0", Some(121675)),
|
||||
/// Allows defining gen blocks and `gen fn`.
|
||||
(unstable, gen_blocks, "1.75.0", Some(117078)),
|
||||
/// Infer generic args for both consts and types.
|
||||
@ -557,6 +559,8 @@ declare_features! (
|
||||
(unstable, offset_of_nested, "1.77.0", Some(120140)),
|
||||
/// Allows using `#[optimize(X)]`.
|
||||
(unstable, optimize_attribute, "1.34.0", Some(54882)),
|
||||
/// Allows postfix match `expr.match { ... }`
|
||||
(unstable, postfix_match, "CURRENT_RUSTC_VERSION", Some(121618)),
|
||||
/// Allows macro attributes on expressions, statements and non-inline modules.
|
||||
(unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
|
||||
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
|
||||
|
@ -810,6 +810,8 @@ pub enum LifetimeRes {
|
||||
param: NodeId,
|
||||
/// Id of the introducing place. See `Param`.
|
||||
binder: NodeId,
|
||||
/// Kind of elided lifetime
|
||||
kind: hir::MissingLifetimeKind,
|
||||
},
|
||||
/// This variant is used for anonymous lifetimes that we did not resolve during
|
||||
/// late resolution. Those lifetimes will be inferred by typechecking.
|
||||
|
@ -428,10 +428,6 @@ pub enum TraitBoundModifier {
|
||||
MaybeConst,
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// `typeck::collect::compute_bounds` matches these against
|
||||
/// the "special" built-in traits (see `middle::lang_items`) and
|
||||
/// detects `Copy`, `Send` and `Sync`.
|
||||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||
pub enum GenericBound<'hir> {
|
||||
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
|
||||
@ -456,6 +452,18 @@ impl GenericBound<'_> {
|
||||
|
||||
pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic, Debug)]
|
||||
pub enum MissingLifetimeKind {
|
||||
/// An explicit `'_`.
|
||||
Underscore,
|
||||
/// An elided lifetime `&' ty`.
|
||||
Ampersand,
|
||||
/// An elided lifetime in brackets with written brackets.
|
||||
Comma,
|
||||
/// An elided lifetime with elided brackets.
|
||||
Brackets,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||
pub enum LifetimeParamKind {
|
||||
// Indicates that the lifetime definition was explicitly declared (e.g., in
|
||||
@ -464,7 +472,7 @@ pub enum LifetimeParamKind {
|
||||
|
||||
// Indication that the lifetime was elided (e.g., in both cases in
|
||||
// `fn foo(x: &u8) -> &'_ u8 { x }`).
|
||||
Elided,
|
||||
Elided(MissingLifetimeKind),
|
||||
|
||||
// Indication that the lifetime name was somehow in error.
|
||||
Error,
|
||||
@ -512,7 +520,7 @@ impl<'hir> GenericParam<'hir> {
|
||||
///
|
||||
/// See `lifetime_to_generic_param` in `rustc_ast_lowering` for more information.
|
||||
pub fn is_elided_lifetime(&self) -> bool {
|
||||
matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided })
|
||||
matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(_) })
|
||||
}
|
||||
}
|
||||
|
||||
@ -1003,7 +1011,7 @@ impl<'hir> Pat<'hir> {
|
||||
use PatKind::*;
|
||||
match self.kind {
|
||||
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
|
||||
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
|
||||
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
|
||||
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
|
||||
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
|
||||
Slice(before, slice, after) => {
|
||||
@ -1030,7 +1038,7 @@ impl<'hir> Pat<'hir> {
|
||||
use PatKind::*;
|
||||
match self.kind {
|
||||
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
|
||||
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
|
||||
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
|
||||
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
|
||||
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
|
||||
Slice(before, slice, after) => {
|
||||
@ -1173,6 +1181,9 @@ pub enum PatKind<'hir> {
|
||||
/// A `box` pattern.
|
||||
Box(&'hir Pat<'hir>),
|
||||
|
||||
/// A `deref` pattern (currently `deref!()` macro-based syntax).
|
||||
Deref(&'hir Pat<'hir>),
|
||||
|
||||
/// A reference pattern (e.g., `&mut (a, b)`).
|
||||
Ref(&'hir Pat<'hir>, Mutability),
|
||||
|
||||
@ -1259,7 +1270,7 @@ pub struct Arm<'hir> {
|
||||
/// In an `if let`, imagine it as `if (let <pat> = <expr>) { ... }`; in a let-else, it is part of
|
||||
/// the desugaring to if-let. Only let-else supports the type annotation at present.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Let<'hir> {
|
||||
pub struct LetExpr<'hir> {
|
||||
pub span: Span,
|
||||
pub pat: &'hir Pat<'hir>,
|
||||
pub ty: Option<&'hir Ty<'hir>>,
|
||||
@ -1845,14 +1856,14 @@ pub enum ExprKind<'hir> {
|
||||
/// Wraps the expression in a terminating scope.
|
||||
/// This makes it semantically equivalent to `{ let _t = expr; _t }`.
|
||||
///
|
||||
/// This construct only exists to tweak the drop order in HIR lowering.
|
||||
/// This construct only exists to tweak the drop order in AST lowering.
|
||||
/// An example of that is the desugaring of `for` loops.
|
||||
DropTemps(&'hir Expr<'hir>),
|
||||
/// A `let $pat = $expr` expression.
|
||||
///
|
||||
/// These are not `Local` and only occur as expressions.
|
||||
/// The `let Some(x) = foo()` in `if let Some(x) = foo()` is an example of `Let(..)`.
|
||||
Let(&'hir Let<'hir>),
|
||||
Let(&'hir LetExpr<'hir>),
|
||||
/// An `if` block, with an optional else block.
|
||||
///
|
||||
/// I.e., `if <expr> { <expr> } else { <expr> }`.
|
||||
@ -2004,6 +2015,8 @@ pub enum LocalSource {
|
||||
pub enum MatchSource {
|
||||
/// A `match _ { .. }`.
|
||||
Normal,
|
||||
/// A `expr.match { .. }`.
|
||||
Postfix,
|
||||
/// A desugared `for _ in _ { .. }` loop.
|
||||
ForLoopDesugar,
|
||||
/// A desugared `?` operator.
|
||||
@ -2020,6 +2033,7 @@ impl MatchSource {
|
||||
use MatchSource::*;
|
||||
match self {
|
||||
Normal => "match",
|
||||
Postfix => ".match",
|
||||
ForLoopDesugar => "for",
|
||||
TryDesugar(_) => "?",
|
||||
AwaitDesugar => ".await",
|
||||
@ -2278,7 +2292,7 @@ pub enum ImplItemKind<'hir> {
|
||||
/// Bind a type to an associated type (i.e., `A = Foo`).
|
||||
///
|
||||
/// Bindings like `A: Debug` are represented as a special type `A =
|
||||
/// $::Debug` that is understood by the astconv code.
|
||||
/// $::Debug` that is understood by the HIR ty lowering code.
|
||||
///
|
||||
/// FIXME(alexreg): why have a separate type for the binding case,
|
||||
/// wouldn't it be better to make the `ty` field an enum like the
|
||||
@ -2552,11 +2566,6 @@ pub struct OpaqueTy<'hir> {
|
||||
pub in_trait: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||
pub struct AssocOpaqueTy {
|
||||
// Add some data if necessary
|
||||
}
|
||||
|
||||
/// From whence the opaque type came.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
|
||||
pub enum OpaqueTyOrigin {
|
||||
@ -3367,7 +3376,7 @@ pub enum OwnerNode<'hir> {
|
||||
TraitItem(&'hir TraitItem<'hir>),
|
||||
ImplItem(&'hir ImplItem<'hir>),
|
||||
Crate(&'hir Mod<'hir>),
|
||||
AssocOpaqueTy(&'hir AssocOpaqueTy),
|
||||
Synthetic,
|
||||
}
|
||||
|
||||
impl<'hir> OwnerNode<'hir> {
|
||||
@ -3377,7 +3386,7 @@ impl<'hir> OwnerNode<'hir> {
|
||||
| OwnerNode::ForeignItem(ForeignItem { ident, .. })
|
||||
| OwnerNode::ImplItem(ImplItem { ident, .. })
|
||||
| OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident),
|
||||
OwnerNode::Crate(..) | OwnerNode::AssocOpaqueTy(..) => None,
|
||||
OwnerNode::Crate(..) | OwnerNode::Synthetic => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -3390,7 +3399,7 @@ impl<'hir> OwnerNode<'hir> {
|
||||
| OwnerNode::ImplItem(ImplItem { span, .. })
|
||||
| OwnerNode::TraitItem(TraitItem { span, .. }) => span,
|
||||
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span,
|
||||
OwnerNode::AssocOpaqueTy(..) => unreachable!(),
|
||||
OwnerNode::Synthetic => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3449,7 +3458,7 @@ impl<'hir> OwnerNode<'hir> {
|
||||
| OwnerNode::ImplItem(ImplItem { owner_id, .. })
|
||||
| OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id,
|
||||
OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
|
||||
OwnerNode::AssocOpaqueTy(..) => unreachable!(),
|
||||
OwnerNode::Synthetic => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3493,7 +3502,7 @@ impl<'hir> Into<Node<'hir>> for OwnerNode<'hir> {
|
||||
OwnerNode::ImplItem(n) => Node::ImplItem(n),
|
||||
OwnerNode::TraitItem(n) => Node::TraitItem(n),
|
||||
OwnerNode::Crate(n) => Node::Crate(n),
|
||||
OwnerNode::AssocOpaqueTy(n) => Node::AssocOpaqueTy(n),
|
||||
OwnerNode::Synthetic => Node::Synthetic,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3531,7 +3540,8 @@ pub enum Node<'hir> {
|
||||
WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>),
|
||||
// FIXME: Merge into `Node::Infer`.
|
||||
ArrayLenInfer(&'hir InferArg),
|
||||
AssocOpaqueTy(&'hir AssocOpaqueTy),
|
||||
// Created by query feeding
|
||||
Synthetic,
|
||||
// Span by reference to minimize `Node`'s size
|
||||
#[allow(rustc::pass_by_value)]
|
||||
Err(&'hir Span),
|
||||
@ -3582,7 +3592,7 @@ impl<'hir> Node<'hir> {
|
||||
| Node::Infer(..)
|
||||
| Node::WhereBoundPredicate(..)
|
||||
| Node::ArrayLenInfer(..)
|
||||
| Node::AssocOpaqueTy(..)
|
||||
| Node::Synthetic
|
||||
| Node::Err(..) => None,
|
||||
}
|
||||
}
|
||||
@ -3640,35 +3650,42 @@ impl<'hir> Node<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body_id(&self) -> Option<BodyId> {
|
||||
#[inline]
|
||||
pub fn associated_body(&self) -> Option<(LocalDefId, BodyId)> {
|
||||
match self {
|
||||
Node::Item(Item {
|
||||
owner_id,
|
||||
kind:
|
||||
ItemKind::Static(_, _, body)
|
||||
| ItemKind::Const(_, _, body)
|
||||
| ItemKind::Fn(_, _, body),
|
||||
ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
|
||||
..
|
||||
})
|
||||
| Node::TraitItem(TraitItem {
|
||||
owner_id,
|
||||
kind:
|
||||
TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
|
||||
TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
|
||||
..
|
||||
})
|
||||
| Node::ImplItem(ImplItem {
|
||||
kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
|
||||
owner_id,
|
||||
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
|
||||
..
|
||||
})
|
||||
| Node::Expr(Expr {
|
||||
kind:
|
||||
ExprKind::ConstBlock(ConstBlock { body, .. })
|
||||
| ExprKind::Closure(Closure { body, .. })
|
||||
| ExprKind::Repeat(_, ArrayLen::Body(AnonConst { body, .. })),
|
||||
..
|
||||
}) => Some(*body),
|
||||
}) => Some((owner_id.def_id, *body)),
|
||||
|
||||
Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
|
||||
Some((*def_id, *body))
|
||||
}
|
||||
|
||||
Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
|
||||
Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body_id(&self) -> Option<BodyId> {
|
||||
Some(self.associated_body()?.1)
|
||||
}
|
||||
|
||||
pub fn generics(self) -> Option<&'hir Generics<'hir>> {
|
||||
match self {
|
||||
Node::ForeignItem(ForeignItem {
|
||||
@ -3688,7 +3705,7 @@ impl<'hir> Node<'hir> {
|
||||
Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
|
||||
Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
|
||||
Node::Crate(i) => Some(OwnerNode::Crate(i)),
|
||||
Node::AssocOpaqueTy(i) => Some(OwnerNode::AssocOpaqueTy(i)),
|
||||
Node::Synthetic => Some(OwnerNode::Synthetic),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -660,7 +660,9 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
|
||||
PatKind::Tuple(tuple_elements, _) => {
|
||||
walk_list!(visitor, visit_pat, tuple_elements);
|
||||
}
|
||||
PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) => {
|
||||
PatKind::Box(ref subpattern)
|
||||
| PatKind::Deref(ref subpattern)
|
||||
| PatKind::Ref(ref subpattern, _) => {
|
||||
try_visit!(visitor.visit_pat(subpattern));
|
||||
}
|
||||
PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => {
|
||||
@ -753,7 +755,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||
ExprKind::DropTemps(ref subexpression) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
}
|
||||
ExprKind::Let(Let { span: _, pat, ty, init, is_recovered: _ }) => {
|
||||
ExprKind::Let(LetExpr { span: _, pat, ty, init, is_recovered: _ }) => {
|
||||
// match the visit order in walk_local
|
||||
try_visit!(visitor.visit_expr(init));
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
|
@ -214,6 +214,7 @@ language_item_table! {
|
||||
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
|
||||
|
||||
Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(let_chains)]
|
||||
#![cfg_attr(bootstrap, feature(min_specialization))]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(variant_count)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! Bounds are restrictions applied to some types after they've been converted into the
|
||||
//! `ty` form from the HIR.
|
||||
//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the
|
||||
//! [`rustc_middle::ty`] form.
|
||||
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
|
||||
|
@ -382,8 +382,8 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
Ok(()) => {}
|
||||
Err(ty_err) => {
|
||||
// Some types may be left "stranded" if they can't be reached
|
||||
// from an astconv'd bound but they're mentioned in the HIR. This
|
||||
// will happen, e.g., when a nested opaque is inside of a non-
|
||||
// from a lowered rustc_middle bound but they're mentioned in the HIR.
|
||||
// This will happen, e.g., when a nested opaque is inside of a non-
|
||||
// existent associated type, like `impl Trait<Missing = impl Trait>`.
|
||||
// See <tests/ui/impl-trait/stranded-opaque.rs>.
|
||||
let ty_err = ty_err.to_string(tcx);
|
||||
|
@ -746,7 +746,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
|
||||
// We may not collect all RPITITs that we see in the HIR for a trait signature
|
||||
// because an RPITIT was located within a missing item. Like if we have a sig
|
||||
// returning `-> Missing<impl Sized>`, that gets converted to `-> [type error]`,
|
||||
// returning `-> Missing<impl Sized>`, that gets converted to `-> {type error}`,
|
||||
// and when walking through the signature we end up never collecting the def id
|
||||
// of the `impl Sized`. Insert that here, so we don't ICE later.
|
||||
for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) {
|
||||
@ -1305,7 +1305,7 @@ fn compare_number_of_generics<'tcx>(
|
||||
.iter()
|
||||
.filter(|p| match p.kind {
|
||||
hir::GenericParamKind::Lifetime {
|
||||
kind: hir::LifetimeParamKind::Elided,
|
||||
kind: hir::LifetimeParamKind::Elided(_),
|
||||
} => {
|
||||
// A fn can have an arbitrary number of extra elided lifetimes for the
|
||||
// same signature.
|
||||
|
@ -441,7 +441,7 @@ pub fn check_intrinsic_type(
|
||||
|
||||
sym::ptr_guaranteed_cmp => (
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
|
||||
tcx.types.u8,
|
||||
),
|
||||
@ -579,7 +579,7 @@ pub fn check_intrinsic_type(
|
||||
|
||||
sym::is_val_statically_known => (1, 1, vec![param(0)], tcx.types.bool),
|
||||
|
||||
sym::const_eval_select => (4, 0, vec![param(0), param(1), param(2)], param(3)),
|
||||
sym::const_eval_select => (4, 1, vec![param(0), param(1), param(2)], param(3)),
|
||||
|
||||
sym::vtable_size | sym::vtable_align => {
|
||||
(0, 0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
|
||||
|
@ -431,7 +431,7 @@ fn fn_sig_suggestion<'tcx>(
|
||||
|
||||
let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
|
||||
output = if let ty::Alias(_, alias_ty) = *output.kind() {
|
||||
tcx.explicit_item_bounds(alias_ty.def_id)
|
||||
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())
|
||||
.unwrap_or_else(|| {
|
||||
|
@ -668,7 +668,7 @@ fn resolve_local<'tcx>(
|
||||
| PatKind::TupleStruct(_, subpats, _)
|
||||
| PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(p)),
|
||||
|
||||
PatKind::Box(subpat) => is_binding_pat(subpat),
|
||||
PatKind::Box(subpat) | PatKind::Deref(subpat) => is_binding_pat(subpat),
|
||||
|
||||
PatKind::Ref(_, _)
|
||||
| PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..)
|
||||
@ -760,7 +760,7 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
|
||||
|
||||
fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) {
|
||||
// If node was previously marked as a terminating scope during the
|
||||
// recursive visit of its parent node in the AST, then we need to
|
||||
// recursive visit of its parent node in the HIR, then we need to
|
||||
// account for the destruction scope representing the scope of
|
||||
// the destructors that run immediately after it completes.
|
||||
if self.terminating_scopes.contains(&id) {
|
||||
|
@ -196,7 +196,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorG
|
||||
hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
|
||||
hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
|
||||
hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
|
||||
hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
|
||||
hir::OwnerNode::Synthetic => unreachable!(),
|
||||
};
|
||||
|
||||
if let Some(generics) = node.generics() {
|
||||
@ -272,7 +272,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
|
||||
}
|
||||
Some(ty::ImplPolarity::Negative) => {
|
||||
let ast::ImplPolarity::Negative(span) = impl_.polarity else {
|
||||
bug!("impl_polarity query disagrees with impl's polarity in AST");
|
||||
bug!("impl_polarity query disagrees with impl's polarity in HIR");
|
||||
};
|
||||
// FIXME(#27579): what amount of WF checking do we need for neg impls?
|
||||
if let hir::Defaultness::Default { .. } = impl_.defaultness {
|
||||
@ -1866,7 +1866,7 @@ fn check_variances_for_type_defn<'tcx>(
|
||||
.iter()
|
||||
.filter_map(|predicate| match predicate {
|
||||
hir::WherePredicate::BoundPredicate(predicate) => {
|
||||
match icx.to_ty(predicate.bounded_ty).kind() {
|
||||
match icx.lower_ty(predicate.bounded_ty).kind() {
|
||||
ty::Param(data) => Some(Parameter(data.index)),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ use std::cell::Cell;
|
||||
use std::iter;
|
||||
use std::ops::Bound;
|
||||
|
||||
use crate::astconv::AstConv;
|
||||
use crate::check::intrinsic::intrinsic_operation_unsafety;
|
||||
use crate::errors;
|
||||
use crate::hir_ty_lowering::HirTyLowerer;
|
||||
pub use type_of::test_opaque_hidden_types;
|
||||
|
||||
mod generics_of;
|
||||
@ -61,6 +61,9 @@ pub fn provide(providers: &mut Providers) {
|
||||
type_alias_is_lazy: type_of::type_alias_is_lazy,
|
||||
item_bounds: item_bounds::item_bounds,
|
||||
explicit_item_bounds: item_bounds::explicit_item_bounds,
|
||||
item_super_predicates: item_bounds::item_super_predicates,
|
||||
explicit_item_super_predicates: item_bounds::explicit_item_super_predicates,
|
||||
item_non_self_assumptions: item_bounds::item_non_self_assumptions,
|
||||
generics_of: generics_of::generics_of,
|
||||
predicates_of: predicates_of::predicates_of,
|
||||
predicates_defined_on,
|
||||
@ -85,13 +88,12 @@ pub fn provide(providers: &mut Providers) {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Context specific to some particular item. This is what implements
|
||||
/// [`AstConv`].
|
||||
/// Context specific to some particular item. This is what implements [`HirTyLowerer`].
|
||||
///
|
||||
/// # `ItemCtxt` vs `FnCtxt`
|
||||
///
|
||||
/// `ItemCtxt` is primarily used to type-check item signatures and lower them
|
||||
/// from HIR to their [`ty::Ty`] representation, which is exposed using [`AstConv`].
|
||||
/// from HIR to their [`ty::Ty`] representation, which is exposed using [`HirTyLowerer`].
|
||||
/// It's also used for the bodies of items like structs where the body (the fields)
|
||||
/// are just signatures.
|
||||
///
|
||||
@ -108,11 +110,11 @@ pub fn provide(providers: &mut Providers) {
|
||||
/// `ItemCtxt` has information about the predicates that are defined
|
||||
/// on the trait. Unfortunately, this predicate information is
|
||||
/// available in various different forms at various points in the
|
||||
/// process. So we can't just store a pointer to e.g., the AST or the
|
||||
/// process. So we can't just store a pointer to e.g., the HIR or the
|
||||
/// parsed ty form, we have to be more flexible. To this end, the
|
||||
/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
|
||||
/// `get_type_parameter_bounds` requests, drawing the information from
|
||||
/// the AST (`hir::Generics`), recursively.
|
||||
/// `probe_ty_param_bounds` requests, drawing the information from
|
||||
/// the HIR (`hir::Generics`), recursively.
|
||||
pub struct ItemCtxt<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item_def_id: LocalDefId,
|
||||
@ -274,7 +276,7 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
convert_item(self.tcx, item.item_id());
|
||||
lower_item(self.tcx, item.item_id());
|
||||
reject_placeholder_type_signatures_in_item(self.tcx, item);
|
||||
intravisit::walk_item(self, item);
|
||||
}
|
||||
@ -312,12 +314,12 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
||||
convert_trait_item(self.tcx, trait_item.trait_item_id());
|
||||
lower_trait_item(self.tcx, trait_item.trait_item_id());
|
||||
intravisit::walk_trait_item(self, trait_item);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
||||
convert_impl_item(self.tcx, impl_item.impl_item_id());
|
||||
lower_impl_item(self.tcx, impl_item.impl_item_id());
|
||||
intravisit::walk_impl_item(self, impl_item);
|
||||
}
|
||||
}
|
||||
@ -341,8 +343,8 @@ impl<'tcx> ItemCtxt<'tcx> {
|
||||
ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
|
||||
}
|
||||
|
||||
pub fn to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.astconv().ast_ty_to_ty(ast_ty)
|
||||
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.lowerer().lower_ty(hir_ty)
|
||||
}
|
||||
|
||||
pub fn hir_id(&self) -> hir::HirId {
|
||||
@ -361,7 +363,7 @@ impl<'tcx> ItemCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
@ -370,23 +372,14 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
self.item_def_id.to_def_id()
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(
|
||||
&self,
|
||||
span: Span,
|
||||
def_id: LocalDefId,
|
||||
assoc_name: Ident,
|
||||
) -> ty::GenericPredicates<'tcx> {
|
||||
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name))
|
||||
fn allow_infer(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn allow_ty_infer(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
|
||||
Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
|
||||
}
|
||||
@ -401,7 +394,16 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant")
|
||||
}
|
||||
|
||||
fn projected_ty_from_poly_trait_ref(
|
||||
fn probe_ty_param_bounds(
|
||||
&self,
|
||||
span: Span,
|
||||
def_id: LocalDefId,
|
||||
assoc_name: Ident,
|
||||
) -> ty::GenericPredicates<'tcx> {
|
||||
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name))
|
||||
}
|
||||
|
||||
fn lower_assoc_ty(
|
||||
&self,
|
||||
span: Span,
|
||||
item_def_id: DefId,
|
||||
@ -409,7 +411,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
|
||||
let item_args = self.astconv().create_args_for_associated_item(
|
||||
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
|
||||
span,
|
||||
item_def_id,
|
||||
item_segment,
|
||||
@ -494,10 +496,6 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
ty.ty_adt_def()
|
||||
}
|
||||
|
||||
fn set_tainted_by_errors(&self, err: ErrorGuaranteed) {
|
||||
self.tainted_by_errors.set(Some(err));
|
||||
}
|
||||
|
||||
fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
|
||||
// There's no place to record types from signatures?
|
||||
}
|
||||
@ -505,6 +503,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_tainted_by_errors(&self, err: ErrorGuaranteed) {
|
||||
self.tainted_by_errors.set(Some(err));
|
||||
}
|
||||
}
|
||||
|
||||
/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
|
||||
@ -544,9 +546,10 @@ fn get_new_lifetime_name<'tcx>(
|
||||
(1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
|
||||
}
|
||||
|
||||
fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
let it = tcx.hir().item(item_id);
|
||||
debug!("convert: item {} with id {}", it.ident, it.hir_id());
|
||||
debug!(item = %it.ident, id = %it.hir_id());
|
||||
let def_id = item_id.owner_id.def_id;
|
||||
|
||||
match &it.kind {
|
||||
@ -588,7 +591,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
convert_enum_variant_types(tcx, def_id.to_def_id());
|
||||
lower_enum_variant_types(tcx, def_id.to_def_id());
|
||||
}
|
||||
hir::ItemKind::Impl { .. } => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
@ -622,7 +625,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
}
|
||||
|
||||
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
|
||||
convert_variant_ctor(tcx, ctor_def_id);
|
||||
lower_variant_ctor(tcx, ctor_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -633,7 +636,9 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure().explicit_item_bounds(def_id);
|
||||
tcx.ensure().explicit_item_super_predicates(def_id);
|
||||
tcx.ensure().item_bounds(def_id);
|
||||
tcx.ensure().item_super_predicates(def_id);
|
||||
}
|
||||
|
||||
hir::ItemKind::TyAlias(..) => {
|
||||
@ -663,7 +668,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
||||
fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
||||
let trait_item = tcx.hir().trait_item(trait_item_id);
|
||||
let def_id = trait_item_id.owner_id;
|
||||
tcx.ensure().generics_of(def_id);
|
||||
@ -689,6 +694,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
||||
|
||||
hir::TraitItemKind::Type(_, Some(_)) => {
|
||||
tcx.ensure().item_bounds(def_id);
|
||||
tcx.ensure().item_super_predicates(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
// Account for `type T = _;`.
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
@ -698,6 +704,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
||||
|
||||
hir::TraitItemKind::Type(_, None) => {
|
||||
tcx.ensure().item_bounds(def_id);
|
||||
tcx.ensure().item_super_predicates(def_id);
|
||||
// #74612: Visit and try to find bad placeholders
|
||||
// even if there is no concrete type.
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
@ -710,7 +717,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
}
|
||||
|
||||
fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
||||
fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
||||
let def_id = impl_item_id.owner_id;
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
@ -739,13 +746,13 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
}
|
||||
|
||||
fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
let def = tcx.adt_def(def_id);
|
||||
let repr_type = def.repr().discr_type();
|
||||
let initial = repr_type.initial_discriminant(tcx);
|
||||
@ -778,10 +785,9 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
tcx.ensure().predicates_of(f.did);
|
||||
}
|
||||
|
||||
// Convert the ctor, if any. This also registers the variant as
|
||||
// an item.
|
||||
// Lower the ctor, if any. This also registers the variant as an item.
|
||||
if let Some(ctor_def_id) = variant.ctor_def_id() {
|
||||
convert_variant_ctor(tcx, ctor_def_id.expect_local());
|
||||
lower_variant_ctor(tcx, ctor_def_id.expect_local());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -968,7 +974,7 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_variant(
|
||||
fn lower_variant(
|
||||
tcx: TyCtxt<'_>,
|
||||
variant_did: Option<LocalDefId>,
|
||||
ident: Ident,
|
||||
@ -1053,7 +1059,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
|
||||
};
|
||||
distance_from_explicit += 1;
|
||||
|
||||
convert_variant(
|
||||
lower_variant(
|
||||
tcx,
|
||||
Some(v.def_id),
|
||||
v.ident,
|
||||
@ -1073,7 +1079,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
|
||||
ItemKind::Struct(..) => AdtKind::Struct,
|
||||
_ => AdtKind::Union,
|
||||
};
|
||||
let variants = std::iter::once(convert_variant(
|
||||
let variants = std::iter::once(lower_variant(
|
||||
tcx,
|
||||
None,
|
||||
item.ident,
|
||||
@ -1277,7 +1283,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
|
||||
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
|
||||
&& i.of_trait.is_some()
|
||||
{
|
||||
icx.astconv().ty_of_fn(
|
||||
icx.lowerer().lower_fn_ty(
|
||||
hir_id,
|
||||
sig.header.unsafety,
|
||||
sig.header.abi,
|
||||
@ -1294,9 +1300,14 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
|
||||
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
|
||||
generics,
|
||||
..
|
||||
}) => {
|
||||
icx.astconv().ty_of_fn(hir_id, header.unsafety, header.abi, decl, Some(generics), None)
|
||||
}
|
||||
}) => icx.lowerer().lower_fn_ty(
|
||||
hir_id,
|
||||
header.unsafety,
|
||||
header.abi,
|
||||
decl,
|
||||
Some(generics),
|
||||
None,
|
||||
),
|
||||
|
||||
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
|
||||
let abi = tcx.hir().get_foreign_abi(hir_id);
|
||||
@ -1364,7 +1375,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||
// recursive function definition to leak out into the fn sig.
|
||||
let mut should_recover = false;
|
||||
|
||||
if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) {
|
||||
if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"replace with the correct return type",
|
||||
@ -1404,7 +1415,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||
))
|
||||
}
|
||||
}
|
||||
None => icx.astconv().ty_of_fn(
|
||||
None => icx.lowerer().lower_fn_ty(
|
||||
hir_id,
|
||||
sig.header.unsafety,
|
||||
sig.header.abi,
|
||||
@ -1442,7 +1453,7 @@ fn suggest_impl_trait<'tcx>(
|
||||
let ty::Tuple(types) = *args_tuple.kind() else {
|
||||
return None;
|
||||
};
|
||||
let types = types.make_suggestable(tcx, false)?;
|
||||
let types = types.make_suggestable(tcx, false, None)?;
|
||||
let maybe_ret =
|
||||
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
|
||||
Some(format!(
|
||||
@ -1500,7 +1511,7 @@ fn suggest_impl_trait<'tcx>(
|
||||
// FIXME(compiler-errors): We may benefit from resolving regions here.
|
||||
if ocx.select_where_possible().is_empty()
|
||||
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
|
||||
&& let Some(item_ty) = item_ty.make_suggestable(tcx, false)
|
||||
&& let Some(item_ty) = item_ty.make_suggestable(tcx, false, None)
|
||||
&& let Some(sugg) = formatter(
|
||||
tcx,
|
||||
infcx.resolve_vars_if_possible(args),
|
||||
@ -1522,19 +1533,19 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
||||
impl_
|
||||
.of_trait
|
||||
.as_ref()
|
||||
.map(|ast_trait_ref| {
|
||||
let selfty = tcx.type_of(def_id).instantiate_identity();
|
||||
.map(|hir_trait_ref| {
|
||||
let self_ty = tcx.type_of(def_id).instantiate_identity();
|
||||
|
||||
let trait_ref = if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
|
||||
tcx,
|
||||
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
|
||||
ast_trait_ref,
|
||||
hir_trait_ref,
|
||||
) {
|
||||
// we have a const impl, but for a trait without `#[const_trait]`, so
|
||||
// without the host param. If we continue with the HIR trait ref, we get
|
||||
// ICEs for generic arg count mismatch. We do a little HIR editing to
|
||||
// make astconv happy.
|
||||
let mut path_segments = ast_trait_ref.path.segments.to_vec();
|
||||
// make HIR ty lowering happy.
|
||||
let mut path_segments = hir_trait_ref.path.segments.to_vec();
|
||||
let last_segment = path_segments.len() - 1;
|
||||
let mut args = *path_segments[last_segment].args();
|
||||
let last_arg = args.args.len() - 1;
|
||||
@ -1542,19 +1553,19 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
||||
args.args = &args.args[..args.args.len() - 1];
|
||||
path_segments[last_segment].args = Some(tcx.hir_arena.alloc(args));
|
||||
let path = hir::Path {
|
||||
span: ast_trait_ref.path.span,
|
||||
res: ast_trait_ref.path.res,
|
||||
span: hir_trait_ref.path.span,
|
||||
res: hir_trait_ref.path.res,
|
||||
segments: tcx.hir_arena.alloc_slice(&path_segments),
|
||||
};
|
||||
let trait_ref = tcx.hir_arena.alloc(hir::TraitRef { path: tcx.hir_arena.alloc(path), hir_ref_id: ast_trait_ref.hir_ref_id });
|
||||
icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty)
|
||||
let trait_ref = tcx.hir_arena.alloc(hir::TraitRef { path: tcx.hir_arena.alloc(path), hir_ref_id: hir_trait_ref.hir_ref_id });
|
||||
icx.lowerer().lower_impl_trait_ref(trait_ref, self_ty)
|
||||
} else {
|
||||
icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
|
||||
icx.lowerer().lower_impl_trait_ref(hir_trait_ref, self_ty)
|
||||
};
|
||||
ty::ImplTraitHeader {
|
||||
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
||||
unsafety: impl_.unsafety,
|
||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span)
|
||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1562,20 +1573,20 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
||||
fn check_impl_constness(
|
||||
tcx: TyCtxt<'_>,
|
||||
is_const: bool,
|
||||
ast_trait_ref: &hir::TraitRef<'_>,
|
||||
hir_trait_ref: &hir::TraitRef<'_>,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if !is_const {
|
||||
return None;
|
||||
}
|
||||
|
||||
let trait_def_id = ast_trait_ref.trait_def_id()?;
|
||||
let trait_def_id = hir_trait_ref.trait_def_id()?;
|
||||
if tcx.has_attr(trait_def_id, sym::const_trait) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let trait_name = tcx.item_name(trait_def_id).to_string();
|
||||
Some(tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
|
||||
trait_ref_span: ast_trait_ref.path.span,
|
||||
trait_ref_span: hir_trait_ref.path.span,
|
||||
trait_name,
|
||||
local_trait_span:
|
||||
trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
|
||||
@ -1671,19 +1682,19 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
|
||||
};
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||
let fty =
|
||||
ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None);
|
||||
ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, unsafety, abi, decl, None, None);
|
||||
|
||||
// Feature gate SIMD types in FFI, since I am not sure that the
|
||||
// ABIs are handled at all correctly. -huonw
|
||||
if abi != abi::Abi::RustIntrinsic && !tcx.features().simd_ffi {
|
||||
let check = |ast_ty: &hir::Ty<'_>, ty: Ty<'_>| {
|
||||
let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
|
||||
if ty.is_simd() {
|
||||
let snip = tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(ast_ty.span)
|
||||
.span_to_snippet(hir_ty.span)
|
||||
.map_or_else(|_| String::new(), |s| format!(" `{s}`"));
|
||||
tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip });
|
||||
tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
|
||||
}
|
||||
};
|
||||
for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
|
||||
|
@ -218,8 +218,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
Deny,
|
||||
}
|
||||
|
||||
let no_generics = hir::Generics::empty();
|
||||
let ast_generics = node.generics().unwrap_or(no_generics);
|
||||
let hir_generics = node.generics().unwrap_or(hir::Generics::empty());
|
||||
let (opt_self, allow_defaults) = match node {
|
||||
Node::Item(item) => {
|
||||
match item.kind {
|
||||
@ -275,13 +274,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
generics.parent_count + generics.params.len()
|
||||
});
|
||||
|
||||
let mut params: Vec<_> = Vec::with_capacity(ast_generics.params.len() + has_self as usize);
|
||||
let mut params: Vec<_> = Vec::with_capacity(hir_generics.params.len() + has_self as usize);
|
||||
|
||||
if let Some(opt_self) = opt_self {
|
||||
params.push(opt_self);
|
||||
}
|
||||
|
||||
let early_lifetimes = super::early_bound_lifetimes_from_generics(tcx, ast_generics);
|
||||
let early_lifetimes = super::early_bound_lifetimes_from_generics(tcx, hir_generics);
|
||||
params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
|
||||
name: param.name.ident().name,
|
||||
index: own_start + i as u32,
|
||||
@ -302,7 +301,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
|
||||
`struct`, `enum`, `type`, or `trait` definitions";
|
||||
|
||||
params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
|
||||
params.extend(hir_generics.params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => None,
|
||||
GenericParamKind::Type { default, synthetic, .. } => {
|
||||
if default.is_some() {
|
||||
@ -508,29 +507,9 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
|
||||
visitor.has_late_bound_regions
|
||||
}
|
||||
|
||||
match node {
|
||||
Node::TraitItem(item) => match &item.kind {
|
||||
hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl),
|
||||
_ => None,
|
||||
},
|
||||
Node::ImplItem(item) => match &item.kind {
|
||||
hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl),
|
||||
_ => None,
|
||||
},
|
||||
Node::ForeignItem(item) => match item.kind {
|
||||
hir::ForeignItemKind::Fn(fn_decl, _, generics) => {
|
||||
has_late_bound_regions(tcx, generics, fn_decl)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
Node::Item(item) => match &item.kind {
|
||||
hir::ItemKind::Fn(sig, .., generics, _) => {
|
||||
has_late_bound_regions(tcx, generics, sig.decl)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
let decl = node.fn_decl()?;
|
||||
let generics = node.generics()?;
|
||||
has_late_bound_regions(tcx, generics, decl)
|
||||
}
|
||||
|
||||
struct AnonConstInParamTyDetector {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use super::ItemCtxt;
|
||||
use crate::astconv::{AstConv, PredicateFilter};
|
||||
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::GenericArgs;
|
||||
@ -17,8 +18,9 @@ use rustc_span::Span;
|
||||
fn associated_type_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
assoc_item_def_id: LocalDefId,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
span: Span,
|
||||
filter: PredicateFilter,
|
||||
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
let item_ty = Ty::new_projection(
|
||||
tcx,
|
||||
@ -27,9 +29,9 @@ fn associated_type_bounds<'tcx>(
|
||||
);
|
||||
|
||||
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
|
||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
|
||||
let mut bounds = icx.lowerer().lower_mono_bounds(item_ty, hir_bounds, filter);
|
||||
// Associated types are implicitly sized unless a `?Sized` bound is found
|
||||
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
||||
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
|
||||
|
||||
let trait_def_id = tcx.local_parent(assoc_item_def_id);
|
||||
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
|
||||
@ -60,15 +62,16 @@ fn associated_type_bounds<'tcx>(
|
||||
fn opaque_type_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaque_def_id: LocalDefId,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
item_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
filter: PredicateFilter,
|
||||
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
ty::print::with_reduced_queries!({
|
||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
|
||||
let mut bounds = icx.lowerer().lower_mono_bounds(item_ty, hir_bounds, filter);
|
||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
||||
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
|
||||
debug!(?bounds);
|
||||
|
||||
tcx.arena.alloc_from_iter(bounds.clauses())
|
||||
@ -78,6 +81,21 @@ fn opaque_type_bounds<'tcx>(
|
||||
pub(super) fn explicit_item_bounds(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
|
||||
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::All)
|
||||
}
|
||||
|
||||
pub(super) fn explicit_item_super_predicates(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
|
||||
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::SelfOnly)
|
||||
}
|
||||
|
||||
pub(super) fn explicit_item_bounds_with_filter(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
filter: PredicateFilter,
|
||||
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
|
||||
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
||||
// RPITIT's bounds are the same as opaque type bounds, but with
|
||||
@ -95,6 +113,7 @@ pub(super) fn explicit_item_bounds(
|
||||
ty::GenericArgs::identity_for_item(tcx, def_id),
|
||||
),
|
||||
item.span,
|
||||
filter,
|
||||
));
|
||||
}
|
||||
Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
|
||||
@ -109,7 +128,7 @@ pub(super) fn explicit_item_bounds(
|
||||
kind: hir::TraitItemKind::Type(bounds, _),
|
||||
span,
|
||||
..
|
||||
}) => associated_type_bounds(tcx, def_id, bounds, *span),
|
||||
}) => associated_type_bounds(tcx, def_id, bounds, *span, filter),
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }),
|
||||
span,
|
||||
@ -117,10 +136,10 @@ pub(super) fn explicit_item_bounds(
|
||||
}) => {
|
||||
let args = GenericArgs::identity_for_item(tcx, def_id);
|
||||
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
|
||||
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
|
||||
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
|
||||
}
|
||||
// Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
|
||||
// for the item bounds of the *opaques* in a trait's default method signature, we
|
||||
// Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're
|
||||
// asking for the item bounds of the *opaques* in a trait's default method signature, we
|
||||
// need to map these projections back to opaques.
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: true, origin, .. }),
|
||||
@ -135,7 +154,7 @@ pub(super) fn explicit_item_bounds(
|
||||
let args = GenericArgs::identity_for_item(tcx, def_id);
|
||||
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
|
||||
tcx.arena.alloc_slice(
|
||||
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
|
||||
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
|
||||
.to_vec()
|
||||
.fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
|
||||
)
|
||||
@ -155,6 +174,31 @@ pub(super) fn item_bounds(
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn item_super_predicates(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
|
||||
tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| {
|
||||
tcx.mk_clauses_from_iter(
|
||||
util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn item_non_self_assumptions(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
|
||||
let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect();
|
||||
let own_bounds: FxIndexSet<_> =
|
||||
tcx.item_super_predicates(def_id).skip_binder().iter().collect();
|
||||
if all_bounds.len() == own_bounds.len() {
|
||||
ty::EarlyBinder::bind(ty::List::empty())
|
||||
} else {
|
||||
ty::EarlyBinder::bind(tcx.mk_clauses_from_iter(all_bounds.difference(&own_bounds).copied()))
|
||||
}
|
||||
}
|
||||
|
||||
struct AssocTyToOpaque<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fn_def_id: DefId,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::ItemCtxt;
|
||||
use crate::constrained_generic_params as cgp;
|
||||
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
|
||||
use hir::{HirId, Node};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
@ -123,43 +123,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
// Preserving the order of insertion is important here so as not to break UI tests.
|
||||
let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
|
||||
|
||||
let ast_generics = match node {
|
||||
Node::TraitItem(item) => item.generics,
|
||||
|
||||
Node::ImplItem(item) => item.generics,
|
||||
|
||||
Node::Item(item) => match item.kind {
|
||||
let hir_generics = node.generics().unwrap_or(NO_GENERICS);
|
||||
if let Node::Item(item) = node {
|
||||
match item.kind {
|
||||
ItemKind::Impl(impl_) => {
|
||||
if impl_.defaultness.is_default() {
|
||||
is_default_impl_trait = tcx
|
||||
.impl_trait_ref(def_id)
|
||||
.map(|t| ty::Binder::dummy(t.instantiate_identity()));
|
||||
}
|
||||
impl_.generics
|
||||
}
|
||||
ItemKind::Fn(.., generics, _)
|
||||
| ItemKind::TyAlias(_, generics)
|
||||
| ItemKind::Const(_, generics, _)
|
||||
| ItemKind::Enum(_, generics)
|
||||
| ItemKind::Struct(_, generics)
|
||||
| ItemKind::Union(_, generics) => generics,
|
||||
|
||||
ItemKind::Trait(_, _, generics, self_bounds, ..)
|
||||
| ItemKind::TraitAlias(generics, self_bounds) => {
|
||||
ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
|
||||
is_trait = Some(self_bounds);
|
||||
generics
|
||||
}
|
||||
ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
|
||||
_ => NO_GENERICS,
|
||||
},
|
||||
|
||||
Node::ForeignItem(item) => match item.kind {
|
||||
ForeignItemKind::Static(..) => NO_GENERICS,
|
||||
ForeignItemKind::Fn(_, _, generics) => generics,
|
||||
ForeignItemKind::Type => NO_GENERICS,
|
||||
},
|
||||
|
||||
_ => NO_GENERICS,
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
@ -170,8 +149,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
// like `trait Foo: A + B + C`.
|
||||
if let Some(self_bounds) = is_trait {
|
||||
predicates.extend(
|
||||
icx.astconv()
|
||||
.compute_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
|
||||
icx.lowerer()
|
||||
.lower_mono_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
|
||||
.clauses(),
|
||||
);
|
||||
}
|
||||
@ -191,19 +170,19 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
// Collect the predicates that were written inline by the user on each
|
||||
// type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
|
||||
// for each const parameter.
|
||||
for param in ast_generics.params {
|
||||
for param in hir_generics.params {
|
||||
match param.kind {
|
||||
// We already dealt with early bound lifetimes above.
|
||||
GenericParamKind::Lifetime { .. } => (),
|
||||
GenericParamKind::Type { .. } => {
|
||||
let param_ty = icx.astconv().hir_id_to_bound_ty(param.hir_id);
|
||||
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
|
||||
let mut bounds = Bounds::default();
|
||||
// Params are implicitly sized unless a `?Sized` bound is found
|
||||
icx.astconv().add_implicitly_sized(
|
||||
icx.lowerer().add_sized_bound(
|
||||
&mut bounds,
|
||||
param_ty,
|
||||
&[],
|
||||
Some((param.def_id, ast_generics.predicates)),
|
||||
Some((param.def_id, hir_generics.predicates)),
|
||||
param.span,
|
||||
);
|
||||
trace!(?bounds);
|
||||
@ -215,7 +194,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
.type_of(param.def_id.to_def_id())
|
||||
.no_bound_vars()
|
||||
.expect("const parameters cannot be generic");
|
||||
let ct = icx.astconv().hir_id_to_bound_const(param.hir_id, ct_ty);
|
||||
let ct = icx.lowerer().lower_const_param(param.hir_id, ct_ty);
|
||||
predicates.insert((
|
||||
ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
|
||||
param.span,
|
||||
@ -226,10 +205,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
|
||||
trace!(?predicates);
|
||||
// Add in the bounds that appear in the where-clause.
|
||||
for predicate in ast_generics.predicates {
|
||||
for predicate in hir_generics.predicates {
|
||||
match predicate {
|
||||
hir::WherePredicate::BoundPredicate(bound_pred) => {
|
||||
let ty = icx.to_ty(bound_pred.bounded_ty);
|
||||
let ty = icx.lower_ty(bound_pred.bounded_ty);
|
||||
let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
|
||||
// Keep the type around in a dummy predicate, in case of no bounds.
|
||||
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
|
||||
@ -253,7 +232,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
}
|
||||
|
||||
let mut bounds = Bounds::default();
|
||||
icx.astconv().add_bounds(
|
||||
icx.lowerer().lower_poly_bounds(
|
||||
ty,
|
||||
bound_pred.bounds.iter(),
|
||||
&mut bounds,
|
||||
@ -264,11 +243,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
}
|
||||
|
||||
hir::WherePredicate::RegionPredicate(region_pred) => {
|
||||
let r1 = icx.astconv().ast_region_to_region(region_pred.lifetime, None);
|
||||
let r1 = icx.lowerer().lower_lifetime(region_pred.lifetime, None);
|
||||
predicates.extend(region_pred.bounds.iter().map(|bound| {
|
||||
let (r2, span) = match bound {
|
||||
hir::GenericBound::Outlives(lt) => {
|
||||
(icx.astconv().ast_region_to_region(lt, None), lt.ident.span)
|
||||
(icx.lowerer().lower_lifetime(lt, None), lt.ident.span)
|
||||
}
|
||||
bound => {
|
||||
span_bug!(
|
||||
@ -563,8 +542,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
||||
}
|
||||
|
||||
/// Ensures that the super-predicates of the trait with a `DefId`
|
||||
/// of `trait_def_id` are converted and stored. This also ensures that
|
||||
/// the transitive super-predicates are converted.
|
||||
/// of `trait_def_id` are lowered and stored. This also ensures that
|
||||
/// the transitive super-predicates are lowered.
|
||||
pub(super) fn super_predicates_of(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_def_id: LocalDefId,
|
||||
@ -595,8 +574,8 @@ pub(super) fn implied_predicates_of(
|
||||
}
|
||||
|
||||
/// Ensures that the super-predicates of the trait with a `DefId`
|
||||
/// of `trait_def_id` are converted and stored. This also ensures that
|
||||
/// the transitive super-predicates are converted.
|
||||
/// of `trait_def_id` are lowered and stored. This also ensures that
|
||||
/// the transitive super-predicates are lowered.
|
||||
pub(super) fn implied_predicates_with_filter(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_def_id: DefId,
|
||||
@ -622,9 +601,9 @@ pub(super) fn implied_predicates_with_filter(
|
||||
let icx = ItemCtxt::new(tcx, trait_def_id);
|
||||
|
||||
let self_param_ty = tcx.types.self_param;
|
||||
let superbounds = icx.astconv().compute_bounds(self_param_ty, bounds, filter);
|
||||
let superbounds = icx.lowerer().lower_mono_bounds(self_param_ty, bounds, filter);
|
||||
|
||||
let where_bounds_that_match = icx.type_parameter_bounds_in_generics(
|
||||
let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics(
|
||||
generics,
|
||||
item.owner_id.def_id,
|
||||
self_param_ty,
|
||||
@ -636,7 +615,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||
&*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match));
|
||||
debug!(?implied_bounds);
|
||||
|
||||
// Now require that immediate supertraits are converted, which will, in
|
||||
// Now require that immediate supertraits are lowered, which will, in
|
||||
// turn, reach indirect supertraits, so we detect cycles now instead of
|
||||
// overflowing during elaboration. Same for implied predicates, which
|
||||
// make sure we walk into associated type bounds.
|
||||
@ -677,7 +656,7 @@ pub(super) fn type_param_predicates(
|
||||
use rustc_hir::*;
|
||||
use rustc_middle::ty::Ty;
|
||||
|
||||
// In the AST, bounds can derive from two places. Either
|
||||
// In the HIR, bounds can derive from two places. Either
|
||||
// written inline like `<T: Foo>` or in a where-clause like
|
||||
// `where T: Foo`.
|
||||
|
||||
@ -697,56 +676,28 @@ pub(super) fn type_param_predicates(
|
||||
let mut result = parent
|
||||
.map(|parent| {
|
||||
let icx = ItemCtxt::new(tcx, parent);
|
||||
icx.get_type_parameter_bounds(DUMMY_SP, def_id, assoc_name)
|
||||
icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_name)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let mut extend = None;
|
||||
|
||||
let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
|
||||
let ast_generics = match tcx.hir_node(item_hir_id) {
|
||||
Node::TraitItem(item) => item.generics,
|
||||
|
||||
Node::ImplItem(item) => item.generics,
|
||||
|
||||
Node::Item(item) => {
|
||||
match item.kind {
|
||||
ItemKind::Fn(.., generics, _)
|
||||
| ItemKind::Impl(&hir::Impl { generics, .. })
|
||||
| ItemKind::TyAlias(_, generics)
|
||||
| ItemKind::Const(_, generics, _)
|
||||
| ItemKind::OpaqueTy(&OpaqueTy {
|
||||
generics,
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
})
|
||||
| ItemKind::Enum(_, generics)
|
||||
| ItemKind::Struct(_, generics)
|
||||
| ItemKind::Union(_, generics) => generics,
|
||||
ItemKind::Trait(_, _, generics, ..) => {
|
||||
// Implied `Self: Trait` and supertrait bounds.
|
||||
if param_id == item_hir_id {
|
||||
let identity_trait_ref =
|
||||
ty::TraitRef::identity(tcx, item_def_id.to_def_id());
|
||||
extend = Some((identity_trait_ref.to_predicate(tcx), item.span));
|
||||
}
|
||||
generics
|
||||
}
|
||||
_ => return result,
|
||||
}
|
||||
}
|
||||
|
||||
Node::ForeignItem(item) => match item.kind {
|
||||
ForeignItemKind::Fn(_, _, generics) => generics,
|
||||
_ => return result,
|
||||
},
|
||||
|
||||
_ => return result,
|
||||
};
|
||||
let hir_node = tcx.hir_node(item_hir_id);
|
||||
let Some(hir_generics) = hir_node.generics() else { return result };
|
||||
if let Node::Item(item) = hir_node
|
||||
&& let ItemKind::Trait(..) = item.kind
|
||||
// Implied `Self: Trait` and supertrait bounds.
|
||||
&& param_id == item_hir_id
|
||||
{
|
||||
let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
|
||||
extend = Some((identity_trait_ref.to_predicate(tcx), item.span));
|
||||
}
|
||||
|
||||
let icx = ItemCtxt::new(tcx, item_def_id);
|
||||
let extra_predicates = extend.into_iter().chain(
|
||||
icx.type_parameter_bounds_in_generics(
|
||||
ast_generics,
|
||||
icx.probe_ty_param_bounds_in_generics(
|
||||
hir_generics,
|
||||
def_id,
|
||||
ty,
|
||||
PredicateFilter::SelfThatDefines(assoc_name),
|
||||
@ -763,21 +714,22 @@ pub(super) fn type_param_predicates(
|
||||
}
|
||||
|
||||
impl<'tcx> ItemCtxt<'tcx> {
|
||||
/// Finds bounds from `hir::Generics`. This requires scanning through the
|
||||
/// AST. We do this to avoid having to convert *all* the bounds, which
|
||||
/// would create artificial cycles. Instead, we can only convert the
|
||||
/// bounds for a type parameter `X` if `X::Foo` is used.
|
||||
#[instrument(level = "trace", skip(self, ast_generics))]
|
||||
fn type_parameter_bounds_in_generics(
|
||||
/// Finds bounds from `hir::Generics`.
|
||||
///
|
||||
/// This requires scanning through the HIR.
|
||||
/// We do this to avoid having to lower *all* the bounds, which would create artificial cycles.
|
||||
/// Instead, we can only lower the bounds for a type parameter `X` if `X::Foo` is used.
|
||||
#[instrument(level = "trace", skip(self, hir_generics))]
|
||||
fn probe_ty_param_bounds_in_generics(
|
||||
&self,
|
||||
ast_generics: &'tcx hir::Generics<'tcx>,
|
||||
hir_generics: &'tcx hir::Generics<'tcx>,
|
||||
param_def_id: LocalDefId,
|
||||
ty: Ty<'tcx>,
|
||||
filter: PredicateFilter,
|
||||
) -> Vec<(ty::Clause<'tcx>, Span)> {
|
||||
let mut bounds = Bounds::default();
|
||||
|
||||
for predicate in ast_generics.predicates {
|
||||
for predicate in hir_generics.predicates {
|
||||
let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
|
||||
continue;
|
||||
};
|
||||
@ -799,13 +751,13 @@ impl<'tcx> ItemCtxt<'tcx> {
|
||||
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
|
||||
ty
|
||||
} else if matches!(filter, PredicateFilter::All) {
|
||||
self.to_ty(predicate.bounded_ty)
|
||||
self.lower_ty(predicate.bounded_ty)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let bound_vars = self.tcx.late_bound_vars(predicate.hir_id);
|
||||
self.astconv().add_bounds(
|
||||
self.lowerer().lower_poly_bounds(
|
||||
bound_ty,
|
||||
predicate.bounds.iter().filter(|bound| {
|
||||
assoc_name
|
||||
|
@ -262,7 +262,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
|
||||
visitor.visit_impl_item(item)
|
||||
}
|
||||
hir::OwnerNode::Crate(_) => {}
|
||||
hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
|
||||
hir::OwnerNode::Synthetic => unreachable!(),
|
||||
}
|
||||
|
||||
let mut rl = ResolveBoundVars::default();
|
||||
@ -1917,18 +1917,18 @@ fn is_late_bound_map(
|
||||
///
|
||||
/// If we conservatively considered `'a` unconstrained then we could break users who had written code before
|
||||
/// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound
|
||||
/// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
|
||||
/// causing an error during HIR ty lowering as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
|
||||
/// but appears in the output type `<() as Trait<'a>>::Assoc`.
|
||||
///
|
||||
/// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not.
|
||||
///
|
||||
/// See #100508 #85533 #47511 for additional context
|
||||
struct ConstrainedCollectorPostAstConv {
|
||||
struct ConstrainedCollectorPostHirTyLowering {
|
||||
arg_is_constrained: Box<[bool]>,
|
||||
}
|
||||
|
||||
use ty::Ty;
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostAstConv {
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostHirTyLowering {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) {
|
||||
match t.kind() {
|
||||
ty::Param(param_ty) => {
|
||||
@ -1970,10 +1970,10 @@ fn is_late_bound_map(
|
||||
None,
|
||||
hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
|
||||
)) => {
|
||||
// See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
|
||||
// args to be unconstrained.
|
||||
// See comments on `ConstrainedCollectorPostHirTyLowering` for why this arm does not
|
||||
// just consider args to be unconstrained.
|
||||
let generics = self.tcx.generics_of(alias_def);
|
||||
let mut walker = ConstrainedCollectorPostAstConv {
|
||||
let mut walker = ConstrainedCollectorPostHirTyLowering {
|
||||
arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
|
||||
};
|
||||
walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
|
||||
|
@ -47,7 +47,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
||||
let ty = tcx.fold_regions(ty, |r, _| {
|
||||
if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r }
|
||||
});
|
||||
let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) {
|
||||
let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false, None) {
|
||||
(ty, Some((span, Applicability::MachineApplicable)))
|
||||
} else {
|
||||
(ty, None)
|
||||
@ -97,10 +97,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
||||
// I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
|
||||
Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
|
||||
// Find the Item containing the associated type so we can create an ItemCtxt.
|
||||
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
|
||||
// Using the ItemCtxt lower the HIR for the unresolved assoc type into a
|
||||
// ty which is a fully resolved projection.
|
||||
// For the code example above, this would mean converting Self::Assoc<3>
|
||||
// into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
|
||||
// For the code example above, this would mean lowering `Self::Assoc<3>`
|
||||
// to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
|
||||
let item_def_id = tcx
|
||||
.hir()
|
||||
.parent_owner_iter(hir_id)
|
||||
@ -108,7 +108,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
||||
.unwrap()
|
||||
.0
|
||||
.def_id;
|
||||
let ty = ItemCtxt::new(tcx, item_def_id).to_ty(hir_ty);
|
||||
let ty = ItemCtxt::new(tcx, item_def_id).lower_ty(hir_ty);
|
||||
|
||||
// Iterate through the generics of the projection to find the one that corresponds to
|
||||
// the def_id that this query was called with. We filter to only type and const args here
|
||||
@ -369,8 +369,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
)
|
||||
})
|
||||
})
|
||||
.unwrap_or_else(|| icx.to_ty(ty)),
|
||||
TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty),
|
||||
.unwrap_or_else(|| icx.lower_ty(ty)),
|
||||
TraitItemKind::Type(_, Some(ty)) => icx.lower_ty(ty),
|
||||
TraitItemKind::Type(_, None) => {
|
||||
span_bug!(item.span, "associated type missing default");
|
||||
}
|
||||
@ -392,7 +392,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
"associated constant",
|
||||
)
|
||||
} else {
|
||||
icx.to_ty(ty)
|
||||
icx.lower_ty(ty)
|
||||
}
|
||||
}
|
||||
ImplItemKind::Type(ty) => {
|
||||
@ -400,7 +400,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
check_feature_inherent_assoc_ty(tcx, item.span);
|
||||
}
|
||||
|
||||
icx.to_ty(ty)
|
||||
icx.lower_ty(ty)
|
||||
}
|
||||
},
|
||||
|
||||
@ -416,17 +416,17 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
"static variable",
|
||||
)
|
||||
} else {
|
||||
icx.to_ty(ty)
|
||||
icx.lower_ty(ty)
|
||||
}
|
||||
}
|
||||
ItemKind::Const(ty, _, body_id) => {
|
||||
if ty.is_suggestable_infer_ty() {
|
||||
infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
|
||||
} else {
|
||||
icx.to_ty(ty)
|
||||
icx.lower_ty(ty)
|
||||
}
|
||||
}
|
||||
ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty),
|
||||
ItemKind::TyAlias(self_ty, _) => icx.lower_ty(self_ty),
|
||||
ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() {
|
||||
spans if spans.len() > 0 => {
|
||||
let guar = tcx
|
||||
@ -434,7 +434,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () });
|
||||
Ty::new_error(tcx, guar)
|
||||
}
|
||||
_ => icx.to_ty(*self_ty),
|
||||
_ => icx.lower_ty(*self_ty),
|
||||
},
|
||||
ItemKind::Fn(..) => {
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
@ -466,7 +466,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
|
||||
}
|
||||
ForeignItemKind::Static(t, _) => icx.to_ty(t),
|
||||
ForeignItemKind::Static(t, _) => icx.lower_ty(t),
|
||||
ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
|
||||
},
|
||||
|
||||
@ -480,7 +480,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
}
|
||||
},
|
||||
|
||||
Node::Field(field) => icx.to_ty(field.ty),
|
||||
Node::Field(field) => icx.lower_ty(field.ty),
|
||||
|
||||
Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => {
|
||||
tcx.typeck(def_id).node_type(hir_id)
|
||||
@ -495,7 +495,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
|
||||
Node::GenericParam(param) => match ¶m.kind {
|
||||
GenericParamKind::Type { default: Some(ty), .. }
|
||||
| GenericParamKind::Const { ty, .. } => icx.to_ty(ty),
|
||||
| GenericParamKind::Const { ty, .. } => icx.lower_ty(ty),
|
||||
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
|
||||
},
|
||||
|
||||
@ -587,7 +587,7 @@ fn infer_placeholder_type<'a>(
|
||||
suggestions.clear();
|
||||
}
|
||||
|
||||
if let Some(ty) = ty.make_suggestable(tcx, false) {
|
||||
if let Some(ty) = ty.make_suggestable(tcx, false, None) {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
format!("provide a type for the {kind}"),
|
||||
@ -606,7 +606,7 @@ fn infer_placeholder_type<'a>(
|
||||
let mut diag = bad_placeholder(tcx, vec![span], kind);
|
||||
|
||||
if !ty.references_error() {
|
||||
if let Some(ty) = ty.make_suggestable(tcx, false) {
|
||||
if let Some(ty) = ty.make_suggestable(tcx, false, None) {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
"replace with the correct type",
|
||||
|
@ -12,17 +12,19 @@ use rustc_trait_selection::traits;
|
||||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
|
||||
use crate::bounds::Bounds;
|
||||
use crate::errors;
|
||||
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
|
||||
|
||||
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
/// Sets `implicitly_sized` to true on `Bounds` if necessary
|
||||
pub(crate) fn add_implicitly_sized(
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Add a `Sized` bound to the `bounds` if appropriate.
|
||||
///
|
||||
/// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`.
|
||||
pub(crate) fn add_sized_bound(
|
||||
&self,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
span: Span,
|
||||
) {
|
||||
@ -33,9 +35,9 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
|
||||
// Try to find an unbound in bounds.
|
||||
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
|
||||
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
|
||||
for ab in ast_bounds {
|
||||
let hir::GenericBound::Trait(ptr, modifier) = ab else {
|
||||
let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
|
||||
for hir_bound in hir_bounds {
|
||||
let hir::GenericBound::Trait(ptr, modifier) = hir_bound else {
|
||||
continue;
|
||||
};
|
||||
match modifier {
|
||||
@ -58,7 +60,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
}
|
||||
};
|
||||
search_bounds(ast_bounds);
|
||||
search_bounds(hir_bounds);
|
||||
if let Some((self_ty, where_clause)) = self_ty_where_predicates {
|
||||
for clause in where_clause {
|
||||
if let hir::WherePredicate::BoundPredicate(pred) = clause
|
||||
@ -101,34 +103,40 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
}
|
||||
|
||||
/// This helper takes a *converted* parameter type (`param_ty`)
|
||||
/// and an *unconverted* list of bounds:
|
||||
/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
|
||||
///
|
||||
/// ```text
|
||||
/// fn foo<T: Debug>
|
||||
/// ^ ^^^^^ `ast_bounds` parameter, in HIR form
|
||||
/// |
|
||||
/// `param_ty`, in ty form
|
||||
/// ### Examples
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn foo<T>() where for<'a> T: Trait<'a> + Copy {}
|
||||
/// // ^^^^^^^ ^ ^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
|
||||
/// // | |
|
||||
/// // | `param_ty`, in ty form
|
||||
/// // `bound_vars`, in ty form
|
||||
///
|
||||
/// fn bar<T>() where T: for<'a> Trait<'a> + Copy {} // no overarching `bound_vars` here!
|
||||
/// // ^ ^^^^^^^^^^^^^^^^^^^^^^^^ `hir_bounds`, in HIR form
|
||||
/// // |
|
||||
/// // `param_ty`, in ty form
|
||||
/// ```
|
||||
///
|
||||
/// It adds these `ast_bounds` into the `bounds` structure.
|
||||
/// ### A Note on Binders
|
||||
///
|
||||
/// **A note on binders:** there is an implied binder around
|
||||
/// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
|
||||
/// for more details.
|
||||
#[instrument(level = "debug", skip(self, ast_bounds, bounds))]
|
||||
pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'tcx>>>(
|
||||
/// There is an implied binder around `param_ty` and `hir_bounds`.
|
||||
/// See `lower_poly_trait_ref` for more details.
|
||||
#[instrument(level = "debug", skip(self, hir_bounds, bounds))]
|
||||
pub(crate) fn lower_poly_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'tcx>>>(
|
||||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: I,
|
||||
hir_bounds: I,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) where
|
||||
'tcx: 'hir,
|
||||
{
|
||||
for ast_bound in ast_bounds {
|
||||
match ast_bound {
|
||||
for hir_bound in hir_bounds {
|
||||
match hir_bound {
|
||||
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
|
||||
let (constness, polarity) = match modifier {
|
||||
hir::TraitBoundModifier::Const => {
|
||||
@ -145,7 +153,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
hir::TraitBoundModifier::Maybe => continue,
|
||||
};
|
||||
let _ = self.instantiate_poly_trait_ref(
|
||||
let _ = self.lower_poly_trait_ref(
|
||||
&poly_trait_ref.trait_ref,
|
||||
poly_trait_ref.span,
|
||||
constness,
|
||||
@ -156,7 +164,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
);
|
||||
}
|
||||
hir::GenericBound::Outlives(lifetime) => {
|
||||
let region = self.ast_region_to_region(lifetime, None);
|
||||
let region = self.lower_lifetime(lifetime, None);
|
||||
bounds.push_region_bound(
|
||||
self.tcx(),
|
||||
ty::Binder::bind_with_vars(
|
||||
@ -170,26 +178,19 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
}
|
||||
|
||||
/// Translates a list of bounds from the HIR into the `Bounds` data structure.
|
||||
/// The self-type for the bounds is given by `param_ty`.
|
||||
/// Lower HIR bounds into `bounds` given the self type `param_ty` and *no* overarching late-bound vars.
|
||||
///
|
||||
/// Example:
|
||||
/// ### Example
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn foo<T: Bar + Baz>() { }
|
||||
/// // ^ ^^^^^^^^^ ast_bounds
|
||||
/// // ^ ^^^^^^^^^ hir_bounds
|
||||
/// // param_ty
|
||||
/// ```
|
||||
///
|
||||
/// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
|
||||
/// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the
|
||||
/// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
|
||||
///
|
||||
/// `span` should be the declaration size of the parameter.
|
||||
pub(crate) fn compute_bounds(
|
||||
pub(crate) fn lower_mono_bounds(
|
||||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: &[hir::GenericBound<'tcx>],
|
||||
hir_bounds: &[hir::GenericBound<'tcx>],
|
||||
filter: PredicateFilter,
|
||||
) -> Bounds<'tcx> {
|
||||
let mut bounds = Bounds::default();
|
||||
@ -201,9 +202,9 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => OnlySelfBounds(true),
|
||||
};
|
||||
|
||||
self.add_bounds(
|
||||
self.lower_poly_bounds(
|
||||
param_ty,
|
||||
ast_bounds.iter().filter(|bound| match filter {
|
||||
hir_bounds.iter().filter(|bound| match filter {
|
||||
PredicateFilter::All
|
||||
| PredicateFilter::SelfOnly
|
||||
| PredicateFilter::SelfAndAssociatedTypeBounds => true,
|
||||
@ -227,14 +228,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
bounds
|
||||
}
|
||||
|
||||
/// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
|
||||
/// onto `bounds`.
|
||||
/// Lower an associated item binding from 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 (e.g., `&'a u32`) and hence may reference bound regions.
|
||||
/// ### 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
|
||||
/// (e.g., `&'a u32`) and hence may reference bound regions.
|
||||
#[instrument(level = "debug", skip(self, bounds, dup_bindings, path_span))]
|
||||
pub(super) fn add_predicates_for_ast_type_binding(
|
||||
pub(super) fn lower_assoc_item_binding(
|
||||
&self,
|
||||
hir_ref_id: hir::HirId,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
@ -244,22 +247,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
path_span: Span,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
// Given something like `U: SomeTrait<T = X>`, we want to produce a
|
||||
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
|
||||
// subtle in the event that `T` is defined in a supertrait of
|
||||
// `SomeTrait`, because in that case we need to upcast.
|
||||
//
|
||||
// That is, consider this case:
|
||||
//
|
||||
// ```
|
||||
// trait SubTrait: SuperTrait<i32> { }
|
||||
// trait SuperTrait<A> { type T; }
|
||||
//
|
||||
// ... B: SubTrait<T = foo> ...
|
||||
// ```
|
||||
//
|
||||
// We want to produce `<B as SuperTrait<i32>>::T == foo`.
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
||||
let assoc_kind = if binding.gen_args.parenthesized
|
||||
@ -272,7 +259,15 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
ty::AssocKind::Type
|
||||
};
|
||||
|
||||
let candidate = if self.trait_defines_associated_item_named(
|
||||
// Given something like `U: Trait<T = X>`, we want to produce a predicate like
|
||||
// `<U as Trait>::T = X`.
|
||||
// This is somewhat subtle in the event that `T` is defined in a supertrait of `Trait`,
|
||||
// because in that case we need to upcast. I.e., we want to produce
|
||||
// `<B as SuperTrait<i32>>::T == X` for `B: SubTrait<T = X>` where
|
||||
//
|
||||
// trait SubTrait: SuperTrait<i32> {}
|
||||
// trait SuperTrait<A> { type T; }
|
||||
let candidate = if self.probe_trait_that_defines_assoc_item(
|
||||
trait_ref.def_id(),
|
||||
assoc_kind,
|
||||
binding.ident,
|
||||
@ -282,7 +277,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
} else {
|
||||
// Otherwise, we have to walk through the supertraits to find
|
||||
// one that does define it.
|
||||
self.one_bound_for_assoc_item(
|
||||
self.probe_single_bound_for_assoc_item(
|
||||
|| traits::supertraits(tcx, trait_ref),
|
||||
trait_ref.skip_binder().print_only_trait_name(),
|
||||
None,
|
||||
@ -417,7 +412,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
infer_args: false,
|
||||
};
|
||||
|
||||
let alias_args = self.create_args_for_associated_item(
|
||||
let alias_args = self.lower_generic_args_of_assoc_item(
|
||||
path_span,
|
||||
assoc_item.def_id,
|
||||
&item_segment,
|
||||
@ -449,9 +444,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
span: binding.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 } => {
|
||||
let term = match term {
|
||||
hir::Term::Ty(ty) => self.ast_ty_to_ty(ty).into(),
|
||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||
hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(),
|
||||
};
|
||||
|
||||
@ -490,10 +487,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
},
|
||||
);
|
||||
|
||||
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
|
||||
// the "projection predicate" for:
|
||||
//
|
||||
// `<T as Iterator>::Item = u32`
|
||||
bounds.push_projection_bound(
|
||||
tcx,
|
||||
projection_ty
|
||||
@ -501,22 +494,18 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
binding.span,
|
||||
);
|
||||
}
|
||||
hir::TypeBindingKind::Constraint { bounds: ast_bounds } => {
|
||||
// "Desugar" a constraint like `T: Iterator<Item: Debug>` to
|
||||
//
|
||||
// `<T as Iterator>::Item: Debug`
|
||||
//
|
||||
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
|
||||
// parameter to have a skipped binder.
|
||||
//
|
||||
// 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.
|
||||
// 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 } => {
|
||||
// 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 {
|
||||
// Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
|
||||
// parameter to have a skipped binder.
|
||||
let param_ty = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
|
||||
self.add_bounds(
|
||||
self.lower_poly_bounds(
|
||||
param_ty,
|
||||
ast_bounds.iter(),
|
||||
hir_bounds.iter(),
|
||||
bounds,
|
||||
projection_ty.bound_vars(),
|
||||
only_self_bounds,
|
||||
@ -565,7 +554,7 @@ fn check_assoc_const_binding_type<'tcx>(
|
||||
let mut guar = ty.visit_with(&mut collector).break_value();
|
||||
|
||||
let ty_note = ty
|
||||
.make_suggestable(tcx, false)
|
||||
.make_suggestable(tcx, false, None)
|
||||
.map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
|
||||
|
||||
let enclosing_item_owner_id = tcx
|
@ -1,9 +1,9 @@
|
||||
use crate::astconv::AstConv;
|
||||
use crate::errors::{
|
||||
self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
|
||||
ParenthesizedFnTraitExpansion,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::hir_ty_lowering::HirTyLowerer;
|
||||
use crate::traits::error_reporting::report_object_safety_error;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
@ -22,7 +22,7 @@ use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
use rustc_trait_selection::traits::object_safety_violations_for_assoc_item;
|
||||
|
||||
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
|
||||
/// the type parameter's name as a placeholder.
|
||||
pub(crate) fn complain_about_missing_type_params(
|
||||
@ -311,7 +311,7 @@ impl<'tcx> dyn AstConv<'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 ty = self.ast_ty_to_ty(hir_ty)
|
||||
&& let ty = self.lower_ty(hir_ty)
|
||||
&& (ty.is_enum() || ty.references_error())
|
||||
&& tcx.features().associated_const_equality
|
||||
{
|
||||
@ -349,7 +349,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn report_ambiguous_associated_type(
|
||||
pub(super) fn report_ambiguous_assoc_ty(
|
||||
&self,
|
||||
span: Span,
|
||||
types: &[String],
|
||||
@ -458,7 +458,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
reported
|
||||
}
|
||||
|
||||
pub(crate) fn complain_about_ambiguous_inherent_assoc_type(
|
||||
pub(crate) fn complain_about_ambiguous_inherent_assoc_ty(
|
||||
&self,
|
||||
name: Ident,
|
||||
candidates: Vec<DefId>,
|
||||
@ -471,14 +471,14 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
"multiple applicable items in scope"
|
||||
);
|
||||
err.span_label(name.span, format!("multiple `{name}` found"));
|
||||
self.note_ambiguous_inherent_assoc_type(&mut err, candidates, span);
|
||||
self.note_ambiguous_inherent_assoc_ty(&mut err, candidates, span);
|
||||
let reported = err.emit();
|
||||
self.set_tainted_by_errors(reported);
|
||||
reported
|
||||
}
|
||||
|
||||
// FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate.
|
||||
fn note_ambiguous_inherent_assoc_type(
|
||||
fn note_ambiguous_inherent_assoc_ty(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
candidates: Vec<DefId>,
|
||||
@ -521,7 +521,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
|
||||
// FIXME(inherent_associated_types): Find similarly named associated types and suggest them.
|
||||
pub(crate) fn complain_about_inherent_assoc_type_not_found(
|
||||
pub(crate) fn complain_about_inherent_assoc_ty_not_found(
|
||||
&self,
|
||||
name: Ident,
|
||||
self_ty: Ty<'tcx>,
|
||||
@ -697,7 +697,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
/// reasonable suggestion on how to write it. For the case of multiple associated types in the
|
||||
/// same trait bound have the same name (as they come from different supertraits), we instead
|
||||
/// emit a generic note suggesting using a `where` clause to constraint instead.
|
||||
pub(crate) fn complain_about_missing_associated_types(
|
||||
pub(crate) fn complain_about_missing_assoc_tys(
|
||||
&self,
|
||||
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
|
||||
potential_assoc_types: Vec<Span>,
|
||||
@ -1027,7 +1027,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
|
||||
/// Emits an error regarding forbidden type binding associations
|
||||
pub fn prohibit_assoc_ty_binding(
|
||||
pub fn prohibit_assoc_item_binding(
|
||||
tcx: TyCtxt<'_>,
|
||||
span: Span,
|
||||
segment: Option<(&hir::PathSegment<'_>, Span)>,
|
@ -1,7 +1,7 @@
|
||||
use super::IsMethodCall;
|
||||
use crate::astconv::{
|
||||
errors::prohibit_assoc_ty_binding, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound,
|
||||
GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
|
||||
use crate::hir_ty_lowering::{
|
||||
errors::prohibit_assoc_item_binding, ExplicitLateBound, GenericArgCountMismatch,
|
||||
GenericArgCountResult, GenericArgPosition, GenericArgsLowerer,
|
||||
};
|
||||
use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs};
|
||||
use rustc_ast::ast::ParamKindOrd;
|
||||
@ -143,24 +143,22 @@ fn generic_arg_mismatch_err(
|
||||
err.emit()
|
||||
}
|
||||
|
||||
/// Creates the relevant generic arguments
|
||||
/// corresponding to a set of generic parameters. This is a
|
||||
/// rather complex function. Let us try to explain the role
|
||||
/// Lower generic arguments from the HIR to the [`rustc_middle::ty`] representation.
|
||||
///
|
||||
/// This is a rather complex function. Let us try to explain the role
|
||||
/// of each of its parameters:
|
||||
///
|
||||
/// To start, we are given the `def_id` of the thing whose generic
|
||||
/// parameters we are instantiating, and a partial set of
|
||||
/// arguments `parent_args`. In general, the generic arguments
|
||||
/// for an item begin with arguments for all the "parents" of
|
||||
/// that item -- e.g., for a method it might include the
|
||||
/// parameters from the impl.
|
||||
/// To start, we are given the `def_id` of the thing whose generic parameters we
|
||||
/// are creating, and a partial set of arguments `parent_args`. In general,
|
||||
/// the generic arguments for an item begin with arguments for all the "parents"
|
||||
/// of that item -- e.g., for a method it might include the parameters from the impl.
|
||||
///
|
||||
/// Therefore, the method begins by walking down these parents,
|
||||
/// starting with the outermost parent and proceed inwards until
|
||||
/// it reaches `def_id`. For each parent `P`, it will check `parent_args`
|
||||
/// first to see if the parent's arguments are listed in there. If so,
|
||||
/// we can append those and move on. Otherwise, it invokes the
|
||||
/// three callback functions:
|
||||
/// we can append those and move on. Otherwise, it uses the provided
|
||||
/// [`GenericArgsLowerer`] `ctx` which has the following methods:
|
||||
///
|
||||
/// - `args_for_def_id`: given the `DefId` `P`, supplies back the
|
||||
/// generic arguments that were given to that parent from within
|
||||
@ -168,18 +166,18 @@ fn generic_arg_mismatch_err(
|
||||
/// might refer to the trait `Foo`, and the arguments might be
|
||||
/// `[T]`. The boolean value indicates whether to infer values
|
||||
/// for arguments whose values were not explicitly provided.
|
||||
/// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
|
||||
/// instantiate a `GenericArg`.
|
||||
/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
|
||||
/// creates a suitable inference variable.
|
||||
pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>(
|
||||
/// - `provided_kind`: given the generic parameter and the value
|
||||
/// from `args_for_def_id`, creating a `GenericArg`.
|
||||
/// - `inferred_kind`: if no parameter was provided, and inference
|
||||
/// is enabled, then creates a suitable inference variable.
|
||||
pub fn lower_generic_args<'tcx: 'a, 'a>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
parent_args: &[ty::GenericArg<'tcx>],
|
||||
has_self: bool,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
arg_count: &GenericArgCountResult,
|
||||
ctx: &mut impl CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>,
|
||||
ctx: &mut impl GenericArgsLowerer<'a, 'tcx>,
|
||||
) -> GenericArgsRef<'tcx> {
|
||||
// Collect the segments of the path; we need to instantiate arguments
|
||||
// for parameters throughout the entire path (wherever there are
|
||||
@ -456,7 +454,7 @@ pub(crate) fn check_generic_arg_count(
|
||||
if gen_pos != GenericArgPosition::Type
|
||||
&& let Some(b) = gen_args.bindings.first()
|
||||
{
|
||||
prohibit_assoc_ty_binding(tcx, b.span, None);
|
||||
prohibit_assoc_item_binding(tcx, b.span, None);
|
||||
}
|
||||
|
||||
let explicit_late_bound =
|
@ -6,9 +6,9 @@ use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
||||
|
||||
use super::AstConv;
|
||||
use super::HirTyLowerer;
|
||||
|
||||
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Make sure that we are in the condition to suggest the blanket implementation.
|
||||
pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>(
|
||||
&self,
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
|
||||
use crate::bounds::Bounds;
|
||||
use crate::errors::TraitObjectDeclaredWithNoTraits;
|
||||
use crate::hir_ty_lowering::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::{codes::*, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
@ -11,14 +11,16 @@ use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::ty::{DynKind, ToPredicate};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
|
||||
use rustc_trait_selection::traits::{self, astconv_object_safety_violations};
|
||||
use rustc_trait_selection::traits::{self, hir_ty_lowering_object_safety_violations};
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use super::AstConv;
|
||||
use super::HirTyLowerer;
|
||||
|
||||
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
pub(super) fn conv_object_ty_poly_trait_ref(
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Lower a trait object type from the HIR to our internal notion of a type.
|
||||
#[instrument(level = "debug", skip_all, ret)]
|
||||
pub(super) fn lower_trait_object_ty(
|
||||
&self,
|
||||
span: Span,
|
||||
hir_id: hir::HirId,
|
||||
@ -37,7 +39,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
correct:
|
||||
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
|
||||
..
|
||||
} = self.instantiate_poly_trait_ref(
|
||||
} = self.lower_poly_trait_ref(
|
||||
&trait_bound.trait_ref,
|
||||
trait_bound.span,
|
||||
ty::BoundConstness::NotConst,
|
||||
@ -133,7 +135,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
// to avoid ICEs.
|
||||
for item in ®ular_traits {
|
||||
let object_safety_violations =
|
||||
astconv_object_safety_violations(tcx, item.trait_ref().def_id());
|
||||
hir_ty_lowering_object_safety_violations(tcx, item.trait_ref().def_id());
|
||||
if !object_safety_violations.is_empty() {
|
||||
let reported = report_object_safety_error(
|
||||
tcx,
|
||||
@ -156,7 +158,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
for (base_trait_ref, span) in regular_traits_refs_spans {
|
||||
let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
|
||||
for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() {
|
||||
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
|
||||
debug!("observing object predicate `{pred:?}`");
|
||||
|
||||
let bound_predicate = pred.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
@ -231,7 +233,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id));
|
||||
}
|
||||
|
||||
self.complain_about_missing_associated_types(
|
||||
self.complain_about_missing_assoc_tys(
|
||||
associated_types,
|
||||
potential_assoc_types,
|
||||
hir_trait_bounds,
|
||||
@ -243,8 +245,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
// the bounds
|
||||
let mut duplicates = FxHashSet::default();
|
||||
auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id()));
|
||||
debug!("regular_traits: {:?}", regular_traits);
|
||||
debug!("auto_traits: {:?}", auto_traits);
|
||||
debug!(?regular_traits);
|
||||
debug!(?auto_traits);
|
||||
|
||||
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
|
||||
let existential_trait_refs = regular_traits.iter().map(|i| {
|
||||
@ -362,11 +364,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
|
||||
// Use explicitly-specified region bound.
|
||||
let region_bound = if !lifetime.is_elided() {
|
||||
self.ast_region_to_region(lifetime, None)
|
||||
self.lower_lifetime(lifetime, None)
|
||||
} else {
|
||||
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
|
||||
if tcx.named_bound_var(lifetime.hir_id).is_some() {
|
||||
self.ast_region_to_region(lifetime, None)
|
||||
self.lower_lifetime(lifetime, None)
|
||||
} else {
|
||||
self.re_infer(None, span).unwrap_or_else(|| {
|
||||
let err = struct_span_code_err!(
|
||||
@ -389,10 +391,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
}
|
||||
})
|
||||
};
|
||||
debug!("region_bound: {:?}", region_bound);
|
||||
debug!(?region_bound);
|
||||
|
||||
let ty = Ty::new_dynamic(tcx, existential_predicates, region_bound, representation);
|
||||
debug!("trait_object_type: {:?}", ty);
|
||||
ty
|
||||
Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
|
||||
}
|
||||
}
|
@ -68,7 +68,7 @@ fn diagnostic_hir_wf_check<'tcx>(
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let tcx_ty = self.icx.to_ty(ty);
|
||||
let tcx_ty = self.icx.lower_ty(ty);
|
||||
// This visitor can walk into binders, resulting in the `tcx_ty` to
|
||||
// potentially reference escaping bound variables. We simply erase
|
||||
// those here.
|
||||
@ -163,6 +163,16 @@ fn diagnostic_hir_wf_check<'tcx>(
|
||||
kind: hir::GenericParamKind::Type { default: Some(ty), .. },
|
||||
..
|
||||
}) => vec![*ty],
|
||||
hir::Node::AnonConst(_)
|
||||
if let Some(const_param_id) =
|
||||
tcx.hir().opt_const_param_default_param_def_id(hir_id)
|
||||
&& let hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { ty, .. },
|
||||
..
|
||||
}) = tcx.hir_node_by_def_id(const_param_id) =>
|
||||
{
|
||||
vec![*ty]
|
||||
}
|
||||
ref node => bug!("Unexpected node {:?}", node),
|
||||
},
|
||||
WellFormedLoc::Param { function: _, param_idx } => {
|
||||
|
@ -30,8 +30,8 @@ several major phases:
|
||||
The type checker is defined into various submodules which are documented
|
||||
independently:
|
||||
|
||||
- astconv: converts the AST representation of types
|
||||
into the `ty` representation.
|
||||
- hir_ty_lowering: lowers type-system entities from the [HIR][hir] to the
|
||||
[`rustc_middle::ty`] representation.
|
||||
|
||||
- collect: computes the types of each top-level item and enters them into
|
||||
the `tcx.types` table for later use.
|
||||
@ -68,7 +68,6 @@ This API is completely unstable and subject to change.
|
||||
#![feature(is_sorted)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![cfg_attr(bootstrap, feature(min_specialization))]
|
||||
#![feature(never_type)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
@ -83,11 +82,11 @@ extern crate rustc_middle;
|
||||
// These are used by Clippy.
|
||||
pub mod check;
|
||||
|
||||
pub mod astconv;
|
||||
pub mod autoderef;
|
||||
mod bounds;
|
||||
mod check_unused;
|
||||
mod coherence;
|
||||
pub mod hir_ty_lowering;
|
||||
// FIXME: This module shouldn't be public.
|
||||
pub mod collect;
|
||||
mod constrained_generic_params;
|
||||
@ -212,12 +211,20 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A quasi-deprecated helper used in rustdoc and clippy to get
|
||||
/// the type from a HIR node.
|
||||
pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
/// Lower a [`hir::Ty`] to a [`Ty`].
|
||||
///
|
||||
/// <div class="warning">
|
||||
///
|
||||
/// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body
|
||||
/// (of a function or constant) and especially if it contains inferred types (`_`).
|
||||
///
|
||||
/// It's used in rustdoc and Clippy.
|
||||
///
|
||||
/// </div>
|
||||
pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
// In case there are any projections, etc., find the "environment"
|
||||
// def-ID that will be used to determine the traits/predicates in
|
||||
// scope. This is derived from the enclosing item-like thing.
|
||||
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
|
||||
collect::ItemCtxt::new(tcx, env_def_id.def_id).to_ty(hir_ty)
|
||||
collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Constraint construction and representation
|
||||
//!
|
||||
//! The second pass over the AST determines the set of constraints.
|
||||
//! The second pass over the HIR determines the set of constraints.
|
||||
//! We walk the set of items and, for each member, generate new constraints.
|
||||
|
||||
use hir::def_id::{DefId, LocalDefId};
|
||||
|
@ -121,7 +121,7 @@ impl<'a> State<'a> {
|
||||
self.print_bounds(":", pred.bounds);
|
||||
}
|
||||
Node::ArrayLenInfer(_) => self.word("_"),
|
||||
Node::AssocOpaqueTy(..) => unreachable!(),
|
||||
Node::Synthetic => unreachable!(),
|
||||
Node::Err(_) => self.word("/*ERROR*/"),
|
||||
}
|
||||
}
|
||||
@ -1387,7 +1387,7 @@ impl<'a> State<'a> {
|
||||
// Print `}`:
|
||||
self.bclose_maybe_open(expr.span, true);
|
||||
}
|
||||
hir::ExprKind::Let(&hir::Let { pat, ty, init, .. }) => {
|
||||
hir::ExprKind::Let(&hir::LetExpr { pat, ty, init, .. }) => {
|
||||
self.print_let(pat, ty, init);
|
||||
}
|
||||
hir::ExprKind::If(test, blk, elseopt) => {
|
||||
@ -1808,6 +1808,12 @@ impl<'a> State<'a> {
|
||||
self.pclose();
|
||||
}
|
||||
}
|
||||
PatKind::Deref(inner) => {
|
||||
self.word("deref!");
|
||||
self.popen();
|
||||
self.print_pat(inner);
|
||||
self.pclose();
|
||||
}
|
||||
PatKind::Ref(inner, mutbl) => {
|
||||
let is_range_inner = matches!(inner.kind, PatKind::Range(..));
|
||||
self.word("&");
|
||||
|
@ -317,7 +317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
err.note("`if` expressions without `else` evaluate to `()`");
|
||||
err.help("consider adding an `else` block that evaluates to the expected type");
|
||||
*error = true;
|
||||
if let ExprKind::Let(hir::Let { span, pat, init, .. }) = cond_expr.kind
|
||||
if let ExprKind::Let(hir::LetExpr { span, pat, init, .. }) = cond_expr.kind
|
||||
&& let ExprKind::Block(block, _) = then_expr.kind
|
||||
// Refutability checks occur on the MIR, so we approximate it here by checking
|
||||
// if we have an enum with a single variant or a struct in the pattern.
|
||||
@ -645,7 +645,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
for ty in [first_ty, second_ty] {
|
||||
for (clause, _) in self
|
||||
.tcx
|
||||
.explicit_item_bounds(rpit_def_id)
|
||||
.explicit_item_super_predicates(rpit_def_id)
|
||||
.iter_instantiated_copied(self.tcx, args)
|
||||
{
|
||||
let pred = clause.kind().rebind(match clause.kind().skip_binder() {
|
||||
|
@ -184,16 +184,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: callee_expr.span,
|
||||
});
|
||||
// We may actually receive a coroutine back whose kind is different
|
||||
// from the closure that this dispatched from. This is because when
|
||||
// we have no captures, we automatically implement `FnOnce`. This
|
||||
// impl forces the closure kind to `FnOnce` i.e. `u8`.
|
||||
let kind_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: callee_expr.span,
|
||||
});
|
||||
let call_sig = self.tcx.mk_fn_sig(
|
||||
[coroutine_closure_sig.tupled_inputs_ty],
|
||||
coroutine_closure_sig.to_coroutine(
|
||||
self.tcx,
|
||||
closure_args.parent_args(),
|
||||
// Inherit the kind ty of the closure, since we're calling this
|
||||
// coroutine with the most relaxed `AsyncFn*` trait that we can.
|
||||
// We don't necessarily need to do this here, but it saves us
|
||||
// computing one more infer var that will get constrained later.
|
||||
closure_args.kind_ty(),
|
||||
kind_ty,
|
||||
self.tcx.coroutine_for_closure(def_id),
|
||||
tupled_upvars_ty,
|
||||
),
|
||||
|
@ -5,7 +5,7 @@ use super::{check_fn, CoroutineTypes, Expectation, FnCtxt};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
|
||||
use rustc_infer::infer::{InferOk, InferResult};
|
||||
@ -262,6 +262,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
},
|
||||
);
|
||||
|
||||
let coroutine_kind_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
});
|
||||
let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||
span: expr_span,
|
||||
@ -279,7 +283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
sig.to_coroutine(
|
||||
tcx,
|
||||
parent_args,
|
||||
closure_kind_ty,
|
||||
coroutine_kind_ty,
|
||||
tcx.coroutine_for_closure(expr_def_id),
|
||||
coroutine_upvars_ty,
|
||||
)
|
||||
@ -325,7 +329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected_ty,
|
||||
closure_kind,
|
||||
self.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.explicit_item_super_predicates(def_id)
|
||||
.iter_instantiated_copied(self.tcx, args)
|
||||
.map(|(c, s)| (c.as_predicate(), s)),
|
||||
),
|
||||
@ -780,7 +784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
decl: &hir::FnDecl<'tcx>,
|
||||
closure_kind: hir::ClosureKind,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
let astconv = self.astconv();
|
||||
let lowerer = self.lowerer();
|
||||
|
||||
trace!("decl = {:#?}", decl);
|
||||
debug!(?closure_kind);
|
||||
@ -789,9 +793,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let bound_vars = self.tcx.late_bound_vars(hir_id);
|
||||
|
||||
// First, convert the types that the user supplied (if any).
|
||||
let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
|
||||
let supplied_arguments = decl.inputs.iter().map(|a| lowerer.lower_ty(a));
|
||||
let supplied_return = match decl.output {
|
||||
hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(output),
|
||||
hir::FnRetTy::Return(ref output) => lowerer.lower_ty(output),
|
||||
hir::FnRetTy::DefaultReturn(_) => match closure_kind {
|
||||
// In the case of the async block that we create for a function body,
|
||||
// we expect the return type of the block to match that of the enclosing
|
||||
@ -809,7 +813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// easily (and locally) prove that we
|
||||
// *have* reported an
|
||||
// error. --nikomatsakis
|
||||
astconv.ty_infer(None, decl.output.span())
|
||||
lowerer.ty_infer(None, decl.output.span())
|
||||
})
|
||||
}
|
||||
// All `gen {}` and `async gen {}` must return unit.
|
||||
@ -828,7 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
| hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_))
|
||||
| hir::ClosureKind::Closure
|
||||
| hir::ClosureKind::CoroutineClosure(_) => {
|
||||
astconv.ty_infer(None, decl.output.span())
|
||||
lowerer.ty_infer(None, decl.output.span())
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -902,7 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
|
||||
.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.explicit_item_super_predicates(def_id)
|
||||
.iter_instantiated_copied(self.tcx, args)
|
||||
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
|
||||
ty::Error(_) => return Some(ret_ty),
|
||||
@ -985,17 +989,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
decl: &hir::FnDecl<'tcx>,
|
||||
guar: ErrorGuaranteed,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
let astconv = self.astconv();
|
||||
let lowerer = self.lowerer();
|
||||
let err_ty = Ty::new_error(self.tcx, guar);
|
||||
|
||||
let supplied_arguments = decl.inputs.iter().map(|a| {
|
||||
// Convert the types that the user supplied (if any), but ignore them.
|
||||
astconv.ast_ty_to_ty(a);
|
||||
lowerer.lower_ty(a);
|
||||
err_ty
|
||||
});
|
||||
|
||||
if let hir::FnRetTy::Return(ref output) = decl.output {
|
||||
astconv.ast_ty_to_ty(output);
|
||||
lowerer.lower_ty(output);
|
||||
}
|
||||
|
||||
let result = ty::Binder::dummy(self.tcx.mk_fn_sig(
|
||||
|
@ -41,7 +41,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::Expr;
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
|
||||
use rustc_infer::traits::TraitEngine;
|
||||
|
@ -35,8 +35,8 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ExprKind, HirId, QPath};
|
||||
use rustc_hir_analysis::astconv::AstConv as _;
|
||||
use rustc_hir_analysis::check::ty_kind_suggestion;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
|
||||
use rustc_infer::infer;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
@ -333,7 +333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
|
||||
ExprKind::Type(e, t) => {
|
||||
let ascribed_ty = self.to_ty_saving_user_provided_ty(t);
|
||||
let ascribed_ty = self.lower_ty_saving_user_provided_ty(t);
|
||||
let ty = self.check_expr_with_hint(e, ascribed_ty);
|
||||
self.demand_eqtype(e.span, ascribed_ty, ty);
|
||||
ascribed_ty
|
||||
@ -1261,7 +1261,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>, hir_id: HirId) -> Ty<'tcx> {
|
||||
pub(super) fn check_expr_let(
|
||||
&self,
|
||||
let_expr: &'tcx hir::LetExpr<'tcx>,
|
||||
hir_id: HirId,
|
||||
) -> Ty<'tcx> {
|
||||
// for let statements, this is done in check_stmt
|
||||
let init = let_expr.init;
|
||||
self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression");
|
||||
@ -1371,7 +1375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
) -> Ty<'tcx> {
|
||||
// Find the type of `e`. Supply hints based on the type we are casting to,
|
||||
// if appropriate.
|
||||
let t_cast = self.to_ty_saving_user_provided_ty(t);
|
||||
let t_cast = self.lower_ty_saving_user_provided_ty(t);
|
||||
let t_cast = self.resolve_vars_if_possible(t_cast);
|
||||
let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
|
||||
let t_expr = self.resolve_vars_if_possible(t_expr);
|
||||
@ -1499,7 +1503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let count = self.array_length_to_const(count);
|
||||
let count = self.lower_array_length(count);
|
||||
if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) {
|
||||
self.suggest_array_len(expr, count);
|
||||
}
|
||||
@ -1675,7 +1679,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expr: &hir::Expr<'_>,
|
||||
span: Span,
|
||||
variant: &'tcx ty::VariantDef,
|
||||
ast_fields: &'tcx [hir::ExprField<'tcx>],
|
||||
hir_fields: &'tcx [hir::ExprField<'tcx>],
|
||||
base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
@ -1706,7 +1710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let mut error_happened = false;
|
||||
|
||||
// Type-check each field.
|
||||
for (idx, field) in ast_fields.iter().enumerate() {
|
||||
for (idx, field) in hir_fields.iter().enumerate() {
|
||||
let ident = tcx.adjust_ident(field.ident, variant.def_id);
|
||||
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
|
||||
seen_fields.insert(ident, field.span);
|
||||
@ -1735,7 +1739,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
variant,
|
||||
expr,
|
||||
field,
|
||||
ast_fields,
|
||||
hir_fields,
|
||||
adt.variant_descr(),
|
||||
)
|
||||
};
|
||||
@ -1750,7 +1754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
|
||||
|
||||
if let Some(diag) = diag {
|
||||
if idx == ast_fields.len() - 1 {
|
||||
if idx == hir_fields.len() - 1 {
|
||||
if remaining_fields.is_empty() {
|
||||
self.suggest_fru_from_range_and_emit(field, variant, args, diag);
|
||||
} else {
|
||||
@ -1764,7 +1768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// Make sure the programmer specified correct number of fields.
|
||||
if adt_kind == AdtKind::Union {
|
||||
if ast_fields.len() != 1 {
|
||||
if hir_fields.len() != 1 {
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
@ -1901,14 +1905,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.collect();
|
||||
|
||||
if !private_fields.is_empty() {
|
||||
self.report_private_fields(adt_ty, span, expr.span, private_fields, ast_fields);
|
||||
self.report_private_fields(adt_ty, span, expr.span, private_fields, hir_fields);
|
||||
} else {
|
||||
self.report_missing_fields(
|
||||
adt_ty,
|
||||
span,
|
||||
remaining_fields,
|
||||
variant,
|
||||
ast_fields,
|
||||
hir_fields,
|
||||
args,
|
||||
);
|
||||
}
|
||||
@ -1945,7 +1949,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
span: Span,
|
||||
remaining_fields: UnordMap<Ident, (FieldIdx, &ty::FieldDef)>,
|
||||
variant: &'tcx ty::VariantDef,
|
||||
ast_fields: &'tcx [hir::ExprField<'tcx>],
|
||||
hir_fields: &'tcx [hir::ExprField<'tcx>],
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) {
|
||||
let len = remaining_fields.len();
|
||||
@ -1982,8 +1986,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}"));
|
||||
|
||||
if let Some(last) = ast_fields.last() {
|
||||
self.suggest_fru_from_range_and_emit(last, variant, args, err);
|
||||
if let Some(hir_field) = hir_fields.last() {
|
||||
self.suggest_fru_from_range_and_emit(hir_field, variant, args, err);
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
@ -3279,7 +3283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
fields: &[Ident],
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let container = self.to_ty(container).normalized;
|
||||
let container = self.lower_ty(container).normalized;
|
||||
|
||||
if let Some(ident_2) = fields.get(1)
|
||||
&& !self.tcx.features().offset_of_nested
|
||||
|
@ -245,7 +245,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
hir::ExprKind::Let(hir::Let { pat, init, .. }) => {
|
||||
hir::ExprKind::Let(hir::LetExpr { pat, init, .. }) => {
|
||||
self.walk_local(init, pat, None, |t| t.borrow_expr(init, ty::ImmBorrow))
|
||||
}
|
||||
|
||||
@ -463,6 +463,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
}
|
||||
PatKind::Or(_)
|
||||
| PatKind::Box(_)
|
||||
| PatKind::Deref(_)
|
||||
| PatKind::Ref(..)
|
||||
| PatKind::Wild
|
||||
| PatKind::Err(_) => {
|
||||
|
@ -4,12 +4,11 @@ use rustc_data_structures::{
|
||||
graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
|
||||
unord::{UnordBag, UnordMap, UnordSet},
|
||||
};
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::sym;
|
||||
|
||||
enum DivergingFallbackBehavior {
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum DivergingFallbackBehavior {
|
||||
/// Always fallback to `()` (aka "always spontaneous decay")
|
||||
FallbackToUnit,
|
||||
/// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken.
|
||||
@ -78,9 +77,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
let diverging_behavior = self.diverging_fallback_behavior();
|
||||
let diverging_fallback =
|
||||
self.calculate_diverging_fallback(&unresolved_variables, diverging_behavior);
|
||||
let diverging_fallback = self
|
||||
.calculate_diverging_fallback(&unresolved_variables, self.diverging_fallback_behavior);
|
||||
|
||||
// We do fallback in two passes, to try to generate
|
||||
// better error messages.
|
||||
@ -94,32 +92,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
fallback_occurred
|
||||
}
|
||||
|
||||
fn diverging_fallback_behavior(&self) -> DivergingFallbackBehavior {
|
||||
let Some((mode, span)) = self
|
||||
.tcx
|
||||
.get_attr(CRATE_DEF_ID, sym::rustc_never_type_mode)
|
||||
.map(|attr| (attr.value_str().unwrap(), attr.span))
|
||||
else {
|
||||
if self.tcx.features().never_type_fallback {
|
||||
return DivergingFallbackBehavior::FallbackToNiko;
|
||||
}
|
||||
|
||||
return DivergingFallbackBehavior::FallbackToUnit;
|
||||
};
|
||||
|
||||
match mode {
|
||||
sym::fallback_to_unit => DivergingFallbackBehavior::FallbackToUnit,
|
||||
sym::fallback_to_niko => DivergingFallbackBehavior::FallbackToNiko,
|
||||
sym::fallback_to_never => DivergingFallbackBehavior::FallbackToNever,
|
||||
sym::no_fallback => DivergingFallbackBehavior::NoFallback,
|
||||
_ => {
|
||||
self.tcx.dcx().span_err(span, format!("unknown never type mode: `{mode}` (supported: `fallback_to_unit`, `fallback_to_niko`, `fallback_to_never` and `no_fallback`)"));
|
||||
|
||||
DivergingFallbackBehavior::FallbackToUnit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fallback_effects(&self) -> bool {
|
||||
let unsolved_effects = self.unsolved_effects();
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user