Auto merge of #3656 - RalfJung:rustup, r=RalfJung
Rustup for `Scalar::from_i128`
This commit is contained in:
commit
989dfb1066
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -156,12 +156,6 @@ jobs:
|
||||
|
||||
- name: checkout submodules
|
||||
run: src/ci/scripts/checkout-submodules.sh
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
if: runner.environment == 'github-hosted'
|
||||
|
||||
- name: install MinGW
|
||||
run: src/ci/scripts/install-mingw.sh
|
||||
|
20
Cargo.lock
20
Cargo.lock
@ -2652,14 +2652,11 @@ version = "0.32.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"hashbrown",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
"ruzstd 0.5.0",
|
||||
"wasmparser",
|
||||
]
|
||||
@ -2675,6 +2672,18 @@ dependencies = [
|
||||
"ruzstd 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "odht"
|
||||
version = "0.3.1"
|
||||
@ -4201,6 +4210,7 @@ dependencies = [
|
||||
"rustc_middle",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_type_ir",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
@ -4392,7 +4402,6 @@ dependencies = [
|
||||
"rustc_hir_pretty",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_next_trait_solver",
|
||||
"rustc_query_system",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
@ -4509,6 +4518,7 @@ dependencies = [
|
||||
"rustc_serialize",
|
||||
"rustc_type_ir",
|
||||
"rustc_type_ir_macros",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5356,7 +5366,7 @@ dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object 0.32.2",
|
||||
"object 0.36.0",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"profiler_builtins",
|
||||
|
@ -488,6 +488,7 @@ pub struct Crate {
|
||||
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct MetaItem {
|
||||
pub unsafety: Safety,
|
||||
pub path: Path,
|
||||
pub kind: MetaItemKind,
|
||||
pub span: Span,
|
||||
@ -1392,7 +1393,7 @@ pub enum ExprKind {
|
||||
/// An array (e.g, `[a, b, c, d]`).
|
||||
Array(ThinVec<P<Expr>>),
|
||||
/// Allow anonymous constants from an inline `const` block
|
||||
ConstBlock(P<Expr>),
|
||||
ConstBlock(AnonConst),
|
||||
/// A function call
|
||||
///
|
||||
/// The first field resolves to the function itself,
|
||||
@ -2823,7 +2824,12 @@ pub struct NormalAttr {
|
||||
impl NormalAttr {
|
||||
pub fn from_ident(ident: Ident) -> Self {
|
||||
Self {
|
||||
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
|
||||
item: AttrItem {
|
||||
unsafety: Safety::Default,
|
||||
path: Path::from_ident(ident),
|
||||
args: AttrArgs::Empty,
|
||||
tokens: None,
|
||||
},
|
||||
tokens: None,
|
||||
}
|
||||
}
|
||||
@ -2831,6 +2837,7 @@ impl NormalAttr {
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct AttrItem {
|
||||
pub unsafety: Safety,
|
||||
pub path: Path,
|
||||
pub args: AttrArgs,
|
||||
// Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.
|
||||
|
@ -1,6 +1,8 @@
|
||||
//! Functions dealing with attributes and meta items.
|
||||
|
||||
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
|
||||
use crate::ast::{
|
||||
AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, Safety,
|
||||
};
|
||||
use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
|
||||
use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
|
||||
use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
|
||||
@ -238,7 +240,12 @@ impl AttrItem {
|
||||
}
|
||||
|
||||
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
|
||||
Some(MetaItem {
|
||||
unsafety: Safety::Default,
|
||||
path: self.path.clone(),
|
||||
kind: self.meta_kind()?,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||
@ -371,7 +378,10 @@ impl MetaItem {
|
||||
_ => path.span.hi(),
|
||||
};
|
||||
let span = path.span.with_hi(hi);
|
||||
Some(MetaItem { path, kind, span })
|
||||
// FIXME: This parses `unsafe()` not as unsafe attribute syntax in `MetaItem`,
|
||||
// but as a parenthesized list. This (and likely `MetaItem`) should be changed in
|
||||
// such a way that builtin macros don't accept extraneous `unsafe()`.
|
||||
Some(MetaItem { unsafety: Safety::Default, path, kind, span })
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,11 +565,12 @@ pub fn mk_doc_comment(
|
||||
pub fn mk_attr(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Safety,
|
||||
path: Path,
|
||||
args: AttrArgs,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
|
||||
mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_from_item(
|
||||
@ -577,15 +588,22 @@ pub fn mk_attr_from_item(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
|
||||
pub fn mk_attr_word(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Safety,
|
||||
name: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Empty;
|
||||
mk_attr(g, style, path, args, span)
|
||||
mk_attr(g, style, unsafety, path, args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_nested_word(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Safety,
|
||||
outer: Symbol,
|
||||
inner: Symbol,
|
||||
span: Span,
|
||||
@ -601,12 +619,13 @@ pub fn mk_attr_nested_word(
|
||||
delim: Delimiter::Parenthesis,
|
||||
tokens: inner_tokens,
|
||||
});
|
||||
mk_attr(g, style, path, attr_args, span)
|
||||
mk_attr(g, style, unsafety, path, attr_args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_name_value_str(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Safety,
|
||||
name: Symbol,
|
||||
val: Symbol,
|
||||
span: Span,
|
||||
@ -621,7 +640,7 @@ pub fn mk_attr_name_value_str(
|
||||
});
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
|
||||
mk_attr(g, style, path, args, span)
|
||||
mk_attr(g, style, unsafety, path, args, span)
|
||||
}
|
||||
|
||||
pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {
|
||||
|
@ -647,8 +647,10 @@ fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||
let Attribute { kind, id: _, style: _, span } = attr;
|
||||
match kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
let NormalAttr { item: AttrItem { path, args, tokens }, tokens: attr_tokens } =
|
||||
&mut **normal;
|
||||
let NormalAttr {
|
||||
item: AttrItem { unsafety: _, path, args, tokens },
|
||||
tokens: attr_tokens,
|
||||
} = &mut **normal;
|
||||
vis.visit_path(path);
|
||||
visit_attr_args(args, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
@ -678,7 +680,7 @@ fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T
|
||||
}
|
||||
|
||||
fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
|
||||
let MetaItem { path: _, kind, span } = mi;
|
||||
let MetaItem { unsafety: _, path: _, kind, span } = mi;
|
||||
match kind {
|
||||
MetaItemKind::Word => {}
|
||||
MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)),
|
||||
@ -840,7 +842,7 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
|
||||
token::NtTy(ty) => vis.visit_ty(ty),
|
||||
token::NtLiteral(expr) => vis.visit_expr(expr),
|
||||
token::NtMeta(item) => {
|
||||
let AttrItem { path, args, tokens } = item.deref_mut();
|
||||
let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
|
||||
vis.visit_path(path);
|
||||
visit_attr_args(args, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
@ -1417,7 +1419,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
match kind {
|
||||
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
|
||||
ExprKind::ConstBlock(anon_const) => {
|
||||
vis.visit_expr(anon_const);
|
||||
vis.visit_anon_const(anon_const);
|
||||
}
|
||||
ExprKind::Repeat(expr, count) => {
|
||||
vis.visit_expr(expr);
|
||||
|
@ -959,7 +959,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
ExprKind::Array(subexpressions) => {
|
||||
walk_list!(visitor, visit_expr, subexpressions);
|
||||
}
|
||||
ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_expr(anon_const)),
|
||||
ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
|
||||
ExprKind::Repeat(element, count) => {
|
||||
try_visit!(visitor.visit_expr(element));
|
||||
try_visit!(visitor.visit_anon_const(count));
|
||||
|
@ -75,8 +75,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let kind = match &e.kind {
|
||||
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
||||
ExprKind::ConstBlock(c) => {
|
||||
self.has_inline_consts = true;
|
||||
hir::ExprKind::ConstBlock(self.lower_expr(c))
|
||||
let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock {
|
||||
def_id: this.local_def_id(c.id),
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
});
|
||||
hir::ExprKind::ConstBlock(c)
|
||||
}
|
||||
ExprKind::Repeat(expr, count) => {
|
||||
let expr = self.lower_expr(expr);
|
||||
@ -1801,6 +1805,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let attr = attr::mk_attr_nested_word(
|
||||
&self.tcx.sess.psess.attr_id_generator,
|
||||
AttrStyle::Outer,
|
||||
Safety::Default,
|
||||
sym::allow,
|
||||
sym::unreachable_code,
|
||||
self.lower_span(span),
|
||||
|
@ -236,6 +236,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_inline_const(&mut self, constant: &'hir ConstBlock) {
|
||||
self.insert(DUMMY_SP, constant.hir_id, Node::ConstBlock(constant));
|
||||
|
||||
self.with_parent(constant.hir_id, |this| {
|
||||
intravisit::walk_inline_const(this, constant);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
|
||||
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
|
||||
|
||||
|
@ -96,8 +96,6 @@ struct LoweringContext<'a, 'hir> {
|
||||
|
||||
/// Bodies inside the owner being lowered.
|
||||
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
|
||||
/// Whether there were inline consts that typeck will split out into bodies
|
||||
has_inline_consts: bool,
|
||||
/// Attributes inside the owner being lowered.
|
||||
attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
|
||||
/// Collect items that were created by lowering the current owner.
|
||||
@ -160,7 +158,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
item_local_id_counter: hir::ItemLocalId::ZERO,
|
||||
node_id_to_local_id: Default::default(),
|
||||
trait_map: Default::default(),
|
||||
has_inline_consts: false,
|
||||
|
||||
// Lowering state.
|
||||
catch_scope: None,
|
||||
@ -570,7 +567,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
let current_attrs = std::mem::take(&mut self.attrs);
|
||||
let current_bodies = std::mem::take(&mut self.bodies);
|
||||
let current_has_inline_consts = std::mem::take(&mut self.has_inline_consts);
|
||||
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
|
||||
let current_trait_map = std::mem::take(&mut self.trait_map);
|
||||
let current_owner =
|
||||
@ -597,7 +593,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
self.attrs = current_attrs;
|
||||
self.bodies = current_bodies;
|
||||
self.has_inline_consts = current_has_inline_consts;
|
||||
self.node_id_to_local_id = current_node_ids;
|
||||
self.trait_map = current_trait_map;
|
||||
self.current_hir_id_owner = current_owner;
|
||||
@ -634,7 +629,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let attrs = std::mem::take(&mut self.attrs);
|
||||
let mut bodies = std::mem::take(&mut self.bodies);
|
||||
let trait_map = std::mem::take(&mut self.trait_map);
|
||||
let has_inline_consts = std::mem::take(&mut self.has_inline_consts);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
for (id, attrs) in attrs.iter() {
|
||||
@ -652,7 +646,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.tcx.hash_owner_nodes(node, &bodies, &attrs);
|
||||
let num_nodes = self.item_local_id_counter.as_usize();
|
||||
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
|
||||
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies, has_inline_consts };
|
||||
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
|
||||
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
|
||||
|
||||
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
|
||||
@ -911,6 +905,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let kind = match attr.kind {
|
||||
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
|
||||
item: AttrItem {
|
||||
unsafety: normal.item.unsafety,
|
||||
path: normal.item.path.clone(),
|
||||
args: self.lower_attr_args(&normal.item.args),
|
||||
tokens: None,
|
||||
|
@ -561,6 +561,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
@ -16,7 +16,7 @@ use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, To
|
||||
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::comments::{Comment, CommentStyle};
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind, Safety};
|
||||
use rustc_ast::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
|
||||
use rustc_ast::{GenericArg, GenericBound, SelfKind};
|
||||
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
||||
@ -249,6 +249,7 @@ pub fn print_crate<'a>(
|
||||
let fake_attr = attr::mk_attr_nested_word(
|
||||
g,
|
||||
ast::AttrStyle::Inner,
|
||||
Safety::Default,
|
||||
sym::feature,
|
||||
sym::prelude_import,
|
||||
DUMMY_SP,
|
||||
@ -259,7 +260,13 @@ pub fn print_crate<'a>(
|
||||
// root, so this is not needed, and actually breaks things.
|
||||
if edition.is_rust_2015() {
|
||||
// `#![no_std]`
|
||||
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
|
||||
let fake_attr = attr::mk_attr_word(
|
||||
g,
|
||||
ast::AttrStyle::Inner,
|
||||
Safety::Default,
|
||||
sym::no_std,
|
||||
DUMMY_SP,
|
||||
);
|
||||
s.print_attribute(&fake_attr);
|
||||
}
|
||||
}
|
||||
|
@ -380,9 +380,8 @@ impl<'a> State<'a> {
|
||||
ast::ExprKind::Array(exprs) => {
|
||||
self.print_expr_vec(exprs);
|
||||
}
|
||||
ast::ExprKind::ConstBlock(expr) => {
|
||||
self.word_space("const");
|
||||
self.print_expr(expr, FixupContext::default());
|
||||
ast::ExprKind::ConstBlock(anon_const) => {
|
||||
self.print_expr_anon_const(anon_const, attrs);
|
||||
}
|
||||
ast::ExprKind::Repeat(element, count) => {
|
||||
self.print_expr_repeat(element, count);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
|
||||
use rustc_span::Span;
|
||||
use std::fmt;
|
||||
use std::ops::Index;
|
||||
@ -97,7 +97,7 @@ pub struct OutlivesConstraint<'tcx> {
|
||||
pub category: ConstraintCategory<'tcx>,
|
||||
|
||||
/// Variance diagnostic information
|
||||
pub variance_info: VarianceDiagInfo<'tcx>,
|
||||
pub variance_info: VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
|
||||
/// If this constraint is promoted from closure requirements.
|
||||
pub from_closure: bool,
|
||||
|
@ -2304,5 +2304,5 @@ pub struct BlameConstraint<'tcx> {
|
||||
pub category: ConstraintCategory<'tcx>,
|
||||
pub from_closure: bool,
|
||||
pub cause: ObligationCause<'tcx>,
|
||||
pub variance_info: ty::VarianceDiagInfo<'tcx>,
|
||||
pub variance_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_infer::infer::relate::{ObligationEmittingRelation, StructurallyRelateAliases};
|
||||
use rustc_infer::infer::relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases};
|
||||
use rustc_infer::traits::{Obligation, PredicateObligations};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::fold::FnMutDelegate;
|
||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
@ -82,7 +82,7 @@ pub struct NllTypeRelating<'me, 'bccx, 'tcx> {
|
||||
/// - Bivariant means that it doesn't matter.
|
||||
ambient_variance: ty::Variance,
|
||||
|
||||
ambient_variance_info: ty::VarianceDiagInfo<'tcx>,
|
||||
ambient_variance_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
||||
@ -296,7 +296,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
||||
&mut self,
|
||||
sup: ty::Region<'tcx>,
|
||||
sub: ty::Region<'tcx>,
|
||||
info: ty::VarianceDiagInfo<'tcx>,
|
||||
info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
) {
|
||||
let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
|
||||
let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
|
||||
@ -314,7 +314,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
||||
impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.type_checker.infcx.tcx
|
||||
}
|
||||
@ -324,10 +324,10 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
||||
}
|
||||
|
||||
#[instrument(skip(self, info), level = "trace", ret)]
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
info: ty::VarianceDiagInfo<'tcx>,
|
||||
info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
@ -445,7 +445,7 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
// We want that
|
||||
//
|
||||
|
@ -110,6 +110,9 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
|
||||
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
|
||||
.suggestion = remove the value
|
||||
|
||||
builtin_macros_derive_unsafe_path = traits in `#[derive(...)]` don't accept `unsafe(...)`
|
||||
.suggestion = remove the `unsafe(...)`
|
||||
|
||||
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
|
||||
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
|
||||
.custom = use `std::env::var({$var_expr})` to read the variable at run time
|
||||
|
@ -17,7 +17,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
|
||||
));
|
||||
|
||||
let start_span = parser.token.span;
|
||||
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||
let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||
Ok(ai) => ai,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
@ -33,6 +33,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
|
||||
krate.attrs.push(mk_attr(
|
||||
&psess.attr_id_generator,
|
||||
AttrStyle::Inner,
|
||||
unsafety,
|
||||
path,
|
||||
args,
|
||||
start_span.to(end_span),
|
||||
|
@ -2,7 +2,7 @@ use crate::cfg_eval::cfg_eval;
|
||||
use crate::errors;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
|
||||
use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, Safety, StmtKind};
|
||||
use rustc_expand::base::{
|
||||
Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier,
|
||||
};
|
||||
@ -60,6 +60,7 @@ impl MultiItemModifier for Expander {
|
||||
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
|
||||
// paths.
|
||||
report_path_args(sess, meta);
|
||||
report_unsafe_args(sess, meta);
|
||||
meta.path.clone()
|
||||
})
|
||||
.map(|path| DeriveResolution {
|
||||
@ -159,3 +160,13 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn report_unsafe_args(sess: &Session, meta: &ast::MetaItem) {
|
||||
match meta.unsafety {
|
||||
Safety::Unsafe(span) => {
|
||||
sess.dcx().emit_err(errors::DeriveUnsafePath { span });
|
||||
}
|
||||
Safety::Default => {}
|
||||
Safety::Safe(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -295,6 +295,13 @@ pub(crate) struct DerivePathArgsValue {
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_derive_unsafe_path)]
|
||||
pub(crate) struct DeriveUnsafePath {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_no_default_variant)]
|
||||
#[help]
|
||||
|
@ -203,6 +203,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
||||
let allow_dead_code = attr::mk_attr_nested_word(
|
||||
&self.sess.psess.attr_id_generator,
|
||||
ast::AttrStyle::Outer,
|
||||
ast::Safety::Default,
|
||||
sym::allow,
|
||||
sym::dead_code,
|
||||
self.def_site,
|
||||
|
@ -38,6 +38,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
|
||||
match node {
|
||||
hir::Node::Ctor(_)
|
||||
| hir::Node::AnonConst(_)
|
||||
| hir::Node::ConstBlock(_)
|
||||
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
|
||||
hir::Constness::Const
|
||||
}
|
||||
@ -56,7 +57,6 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
|
||||
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
|
||||
}
|
||||
hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
|
||||
hir::Node::Expr(e) if let hir::ExprKind::ConstBlock(_) = e.kind => hir::Constness::Const,
|
||||
_ => {
|
||||
if let Some(fn_kind) = node.fn_kind() {
|
||||
if fn_kind.constness() == hir::Constness::Const {
|
||||
|
@ -666,7 +666,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
// Builds `#[name]`.
|
||||
pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
|
||||
let g = &self.sess.psess.attr_id_generator;
|
||||
attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
|
||||
attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Safety::Default, name, span)
|
||||
}
|
||||
|
||||
// Builds `#[name = val]`.
|
||||
@ -674,12 +674,26 @@ impl<'a> ExtCtxt<'a> {
|
||||
// Note: `span` is used for both the identifier and the value.
|
||||
pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
|
||||
let g = &self.sess.psess.attr_id_generator;
|
||||
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
|
||||
attr::mk_attr_name_value_str(
|
||||
g,
|
||||
ast::AttrStyle::Outer,
|
||||
ast::Safety::Default,
|
||||
name,
|
||||
val,
|
||||
span,
|
||||
)
|
||||
}
|
||||
|
||||
// Builds `#[outer(inner)]`.
|
||||
pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
|
||||
let g = &self.sess.psess.attr_id_generator;
|
||||
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
|
||||
attr::mk_attr_nested_word(
|
||||
g,
|
||||
ast::AttrStyle::Outer,
|
||||
ast::Safety::Default,
|
||||
outer,
|
||||
inner,
|
||||
span,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -778,7 +778,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
if let SyntaxExtensionKind::Derive(..) = ext {
|
||||
self.gate_proc_macro_input(&item);
|
||||
}
|
||||
let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path };
|
||||
// The `MetaItem` representing the trait to derive can't
|
||||
// have an unsafe around it (as of now).
|
||||
let meta = ast::MetaItem {
|
||||
unsafety: ast::Safety::Default,
|
||||
kind: MetaItemKind::Word,
|
||||
span,
|
||||
path,
|
||||
};
|
||||
let items = match expander.expand(self.cx, span, &meta, item, is_const) {
|
||||
ExpandResult::Ready(items) => items,
|
||||
ExpandResult::Retry(item) => {
|
||||
|
@ -59,6 +59,16 @@ pub enum AttributeType {
|
||||
CrateLevel,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum AttributeSafety {
|
||||
/// Normal attribute that does not need `#[unsafe(...)]`
|
||||
Normal,
|
||||
|
||||
/// Unsafe attribute that requires safety obligations
|
||||
/// to be discharged
|
||||
Unsafe,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AttributeGate {
|
||||
/// Is gated by a given feature gate, reason
|
||||
@ -172,11 +182,23 @@ macro_rules! template {
|
||||
}
|
||||
|
||||
macro_rules! ungated {
|
||||
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Unsafe,
|
||||
template: $tpl,
|
||||
gate: Ungated,
|
||||
duplicates: $duplicates,
|
||||
}
|
||||
};
|
||||
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
gate: Ungated,
|
||||
duplicates: $duplicates,
|
||||
@ -185,11 +207,34 @@ macro_rules! ungated {
|
||||
}
|
||||
|
||||
macro_rules! gated {
|
||||
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Unsafe,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
|
||||
}
|
||||
};
|
||||
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Unsafe,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
|
||||
}
|
||||
};
|
||||
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
|
||||
@ -200,6 +245,7 @@ macro_rules! gated {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
|
||||
@ -228,6 +274,7 @@ macro_rules! rustc_attr {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
|
||||
@ -258,6 +305,7 @@ pub struct BuiltinAttribute {
|
||||
/// Otherwise, it can only be used in the local crate.
|
||||
pub encode_cross_crate: EncodeCrossCrate,
|
||||
pub type_: AttributeType,
|
||||
pub safety: AttributeSafety,
|
||||
pub template: AttributeTemplate,
|
||||
pub duplicates: AttributeDuplicates,
|
||||
pub gate: AttributeGate,
|
||||
@ -375,9 +423,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
),
|
||||
ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
|
||||
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
|
||||
|
||||
@ -486,11 +534,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
),
|
||||
|
||||
gated!(
|
||||
ffi_pure, Normal, template!(Word), WarnFollowing,
|
||||
unsafe ffi_pure, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::No, experimental!(ffi_pure)
|
||||
),
|
||||
gated!(
|
||||
ffi_const, Normal, template!(Word), WarnFollowing,
|
||||
unsafe ffi_const, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::No, experimental!(ffi_const)
|
||||
),
|
||||
gated!(
|
||||
@ -850,6 +898,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
|
||||
encode_cross_crate: EncodeCrossCrate::Yes,
|
||||
type_: Normal,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: template!(NameValueStr: "name"),
|
||||
duplicates: ErrorFollowing,
|
||||
gate: Gated(
|
||||
@ -1096,6 +1145,10 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_unsafe_attr(name: Symbol) -> bool {
|
||||
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.safety == AttributeSafety::Unsafe)
|
||||
}
|
||||
|
||||
pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
|
||||
LazyLock::new(|| {
|
||||
let mut map = FxHashMap::default();
|
||||
|
@ -123,8 +123,8 @@ pub use accepted::ACCEPTED_FEATURES;
|
||||
pub use builtin_attrs::AttributeDuplicates;
|
||||
pub use builtin_attrs::{
|
||||
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,
|
||||
is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
|
||||
BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
|
||||
};
|
||||
pub use removed::REMOVED_FEATURES;
|
||||
pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES};
|
||||
|
@ -620,6 +620,8 @@ declare_features! (
|
||||
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
||||
/// Allows unnamed fields of struct and union type
|
||||
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
|
||||
/// Allows unsafe attributes.
|
||||
(unstable, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
|
||||
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
|
||||
(unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
|
||||
/// Allows unsized fn parameters.
|
||||
|
@ -907,9 +907,6 @@ pub struct OwnerNodes<'tcx> {
|
||||
pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>,
|
||||
/// Content of local bodies.
|
||||
pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
|
||||
/// Whether the body contains inline constants that are created for the query system during typeck
|
||||
/// of the body.
|
||||
pub has_inline_consts: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> OwnerNodes<'tcx> {
|
||||
@ -1626,6 +1623,14 @@ pub struct AnonConst {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// An inline constant expression `const { something }`.
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||
pub struct ConstBlock {
|
||||
pub hir_id: HirId,
|
||||
pub def_id: LocalDefId,
|
||||
pub body: BodyId,
|
||||
}
|
||||
|
||||
/// An expression.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Expr<'hir> {
|
||||
@ -1912,7 +1917,7 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum ExprKind<'hir> {
|
||||
/// Allow anonymous constants from an inline `const` block
|
||||
ConstBlock(&'hir Expr<'hir>),
|
||||
ConstBlock(ConstBlock),
|
||||
/// An array (e.g., `[a, b, c, d]`).
|
||||
Array(&'hir [Expr<'hir>]),
|
||||
/// A function call.
|
||||
@ -2345,7 +2350,9 @@ impl ImplItemId {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents anything within an `impl` block.
|
||||
/// Represents an associated item within an impl block.
|
||||
///
|
||||
/// Refer to [`Impl`] for an impl block declaration.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct ImplItem<'hir> {
|
||||
pub ident: Ident,
|
||||
@ -3327,6 +3334,10 @@ pub enum ItemKind<'hir> {
|
||||
Impl(&'hir Impl<'hir>),
|
||||
}
|
||||
|
||||
/// Represents an impl block declaration.
|
||||
///
|
||||
/// E.g., `impl $Type { .. }` or `impl $Trait for $Type { .. }`
|
||||
/// Refer to [`ImplItem`] for an associated item within an impl block.
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Impl<'hir> {
|
||||
pub safety: Safety,
|
||||
@ -3644,6 +3655,7 @@ pub enum Node<'hir> {
|
||||
Variant(&'hir Variant<'hir>),
|
||||
Field(&'hir FieldDef<'hir>),
|
||||
AnonConst(&'hir AnonConst),
|
||||
ConstBlock(&'hir ConstBlock),
|
||||
Expr(&'hir Expr<'hir>),
|
||||
ExprField(&'hir ExprField<'hir>),
|
||||
Stmt(&'hir Stmt<'hir>),
|
||||
@ -3704,6 +3716,7 @@ impl<'hir> Node<'hir> {
|
||||
Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
|
||||
Node::Param(..)
|
||||
| Node::AnonConst(..)
|
||||
| Node::ConstBlock(..)
|
||||
| Node::Expr(..)
|
||||
| Node::Stmt(..)
|
||||
| Node::Block(..)
|
||||
@ -3801,6 +3814,7 @@ impl<'hir> Node<'hir> {
|
||||
}
|
||||
|
||||
Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
|
||||
Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
@ -3869,6 +3883,7 @@ impl<'hir> Node<'hir> {
|
||||
expect_variant, &'hir Variant<'hir>, Node::Variant(n), n;
|
||||
expect_field, &'hir FieldDef<'hir>, Node::Field(n), n;
|
||||
expect_anon_const, &'hir AnonConst, Node::AnonConst(n), n;
|
||||
expect_inline_const, &'hir ConstBlock, Node::ConstBlock(n), n;
|
||||
expect_expr, &'hir Expr<'hir>, Node::Expr(n), n;
|
||||
expect_expr_field, &'hir ExprField<'hir>, Node::ExprField(n), n;
|
||||
expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n;
|
||||
|
@ -344,6 +344,9 @@ pub trait Visitor<'v>: Sized {
|
||||
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
|
||||
walk_anon_const(self, c)
|
||||
}
|
||||
fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
|
||||
walk_inline_const(self, c)
|
||||
}
|
||||
fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
|
||||
walk_expr(self, ex)
|
||||
}
|
||||
@ -718,6 +721,14 @@ pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonCo
|
||||
visitor.visit_nested_body(constant.body)
|
||||
}
|
||||
|
||||
pub fn walk_inline_const<'v, V: Visitor<'v>>(
|
||||
visitor: &mut V,
|
||||
constant: &'v ConstBlock,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_id(constant.hir_id));
|
||||
visitor.visit_nested_body(constant.body)
|
||||
}
|
||||
|
||||
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
|
||||
try_visit!(visitor.visit_id(expression.hir_id));
|
||||
match expression.kind {
|
||||
@ -725,7 +736,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||
walk_list!(visitor, visit_expr, subexpressions);
|
||||
}
|
||||
ExprKind::ConstBlock(ref const_block) => {
|
||||
try_visit!(visitor.visit_expr(const_block))
|
||||
try_visit!(visitor.visit_inline_const(const_block))
|
||||
}
|
||||
ExprKind::Repeat(ref element, ref count) => {
|
||||
try_visit!(visitor.visit_expr(element));
|
||||
|
@ -93,8 +93,7 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'
|
||||
// `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
|
||||
// the body satisfies the condition of two nodes being different have different
|
||||
// `hash_stable` results.
|
||||
let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _, has_inline_consts: _ } =
|
||||
*self;
|
||||
let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self;
|
||||
opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
||||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||
use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
|
||||
|
@ -407,14 +407,11 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
|
||||
match expr.kind {
|
||||
// Manually recurse over closures and inline consts, because they are the only
|
||||
// case of nested bodies that share the parent environment.
|
||||
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
|
||||
hir::ExprKind::Closure(&hir::Closure { body, .. })
|
||||
| hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) => {
|
||||
let body = visitor.tcx.hir().body(body);
|
||||
visitor.visit_body(body);
|
||||
}
|
||||
hir::ExprKind::ConstBlock(expr) => visitor.enter_body(expr.hir_id, |this| {
|
||||
this.cx.var_parent = None;
|
||||
resolve_local(this, None, Some(expr));
|
||||
}),
|
||||
hir::ExprKind::AssignOp(_, left_expr, right_expr) => {
|
||||
debug!(
|
||||
"resolve_expr - enabling pessimistic_yield, was previously {}",
|
||||
|
@ -177,10 +177,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
}
|
||||
}
|
||||
}
|
||||
Node::Expr(&hir::Expr {
|
||||
kind: hir::ExprKind::Closure { .. } | hir::ExprKind::ConstBlock { .. },
|
||||
..
|
||||
}) => Some(tcx.typeck_root_def_id(def_id.to_def_id())),
|
||||
Node::ConstBlock(_)
|
||||
| Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
|
||||
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
|
||||
}
|
||||
Node::Item(item) => match item.kind {
|
||||
ItemKind::OpaqueTy(&hir::OpaqueTy {
|
||||
origin:
|
||||
@ -415,7 +415,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
}
|
||||
|
||||
// provide junk type parameter defs for const blocks.
|
||||
if let Node::Expr(Expr { kind: ExprKind::ConstBlock(..), .. }) = node {
|
||||
if let Node::ConstBlock(_) = node {
|
||||
own_params.push(ty::GenericParamDef {
|
||||
index: next_index(),
|
||||
name: Symbol::intern("<const_ty>"),
|
||||
|
@ -485,7 +485,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
|
||||
}
|
||||
|
||||
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
|
||||
Node::Expr(&Expr { kind: ExprKind::ConstBlock(..), .. }) => {
|
||||
|
||||
Node::ConstBlock(_) => {
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());
|
||||
args.as_inline_const().ty()
|
||||
}
|
||||
|
@ -190,6 +190,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
}
|
||||
});
|
||||
|
||||
// Freeze definitions as we don't add new ones at this point. This improves performance by
|
||||
// allowing lock-free access to them.
|
||||
tcx.untracked().definitions.freeze();
|
||||
|
||||
// FIXME: Remove this when we implement creating `DefId`s
|
||||
// for anon constants during their parents' typeck.
|
||||
// Typeck all body owners in parallel will produce queries
|
||||
@ -201,10 +205,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
}
|
||||
});
|
||||
|
||||
// Freeze definitions as we don't add new ones at this point. This improves performance by
|
||||
// allowing lock-free access to them.
|
||||
tcx.untracked().definitions.freeze();
|
||||
|
||||
tcx.ensure().check_unused_traits(());
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ impl<'a> State<'a> {
|
||||
Node::ImplItem(a) => self.print_impl_item(a),
|
||||
Node::Variant(a) => self.print_variant(a),
|
||||
Node::AnonConst(a) => self.print_anon_const(a),
|
||||
Node::ConstBlock(a) => self.print_inline_const(a),
|
||||
Node::Expr(a) => self.print_expr(a),
|
||||
Node::ExprField(a) => self.print_expr_field(a),
|
||||
Node::Stmt(a) => self.print_stmt(a),
|
||||
@ -1049,10 +1050,10 @@ impl<'a> State<'a> {
|
||||
self.end()
|
||||
}
|
||||
|
||||
fn print_inline_const(&mut self, constant: &hir::Expr<'_>) {
|
||||
fn print_inline_const(&mut self, constant: &hir::ConstBlock) {
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word_space("const");
|
||||
self.print_expr(constant);
|
||||
self.ann.nested(self, Nested::Body(constant.body));
|
||||
self.end()
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_infer::infer::relate::RelateResult;
|
||||
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
|
||||
use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause};
|
||||
use rustc_infer::traits::{Obligation, PredicateObligation};
|
||||
@ -51,7 +52,6 @@ use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
|
||||
};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_session::parse::feature_err;
|
||||
|
@ -31,6 +31,7 @@ use rustc_errors::{
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
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::hir_ty_lowering::HirTyLowerer as _;
|
||||
@ -40,7 +41,7 @@ use rustc_infer::infer::InferOk;
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError::Sorts};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
@ -334,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
|
||||
ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
|
||||
ExprKind::ConstBlock(ref block) => self.check_expr_with_expectation(block, expected),
|
||||
ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected),
|
||||
ExprKind::Repeat(element, ref count) => {
|
||||
self.check_expr_repeat(element, count, expected, expr)
|
||||
}
|
||||
@ -682,7 +683,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.suggest_mismatched_types_on_tail(
|
||||
&mut err, expr, ty, e_ty, target_id,
|
||||
);
|
||||
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
|
||||
let error =
|
||||
Some(TypeError::Sorts(ExpectedFound { expected: ty, found: e_ty }));
|
||||
self.annotate_loop_expected_due_to_inference(err, expr, error);
|
||||
if let Some(val) =
|
||||
self.err_ctxt().ty_kind_suggestion(self.param_env, ty)
|
||||
@ -1456,6 +1458,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_const_block(
|
||||
&self,
|
||||
block: &'tcx hir::ConstBlock,
|
||||
expected: Expectation<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let body = self.tcx.hir().body(block.body);
|
||||
|
||||
// Create a new function context.
|
||||
let def_id = block.def_id;
|
||||
let fcx = FnCtxt::new(self, self.param_env, def_id);
|
||||
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
|
||||
|
||||
let ty = fcx.check_expr_with_expectation(body.value, expected);
|
||||
fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized);
|
||||
fcx.write_ty(block.hir_id, ty);
|
||||
ty
|
||||
}
|
||||
|
||||
fn check_expr_repeat(
|
||||
&self,
|
||||
element: &'tcx hir::Expr<'tcx>,
|
||||
|
@ -1051,10 +1051,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.take_while(|(_, node)| {
|
||||
// look at parents until we find the first body owner
|
||||
node.body_id().is_none()
|
||||
&& !matches!(
|
||||
node,
|
||||
Node::Expr(Expr { kind: ExprKind::ConstBlock { .. }, .. })
|
||||
)
|
||||
})
|
||||
.any(|(parent_id, _)| self.is_loop(parent_id));
|
||||
|
||||
|
@ -149,6 +149,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
|
||||
self.visit_body(body);
|
||||
self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
|
||||
}
|
||||
hir::ExprKind::ConstBlock(anon_const) => {
|
||||
let body = self.fcx.tcx.hir().body(anon_const.body);
|
||||
self.visit_body(body);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
// generic parameters.
|
||||
|
||||
use crate::FnCtxt;
|
||||
use hir::def::DefKind;
|
||||
use rustc_data_structures::unord::ExtendUnord;
|
||||
use rustc_errors::{ErrorGuaranteed, StashKey};
|
||||
use rustc_hir as hir;
|
||||
@ -17,7 +16,7 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::TypeSuperFoldable;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::solve;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
@ -296,11 +295,11 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
||||
hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
|
||||
self.visit_field_id(e.hir_id);
|
||||
}
|
||||
hir::ExprKind::ConstBlock(_) => {
|
||||
let feed = self.tcx().create_def(self.fcx.body_id, kw::Empty, DefKind::InlineConst);
|
||||
feed.def_span(e.span);
|
||||
feed.local_def_id_to_hir_id(e.hir_id);
|
||||
self.typeck_results.inline_consts.insert(e.hir_id.local_id, feed.def_id());
|
||||
hir::ExprKind::ConstBlock(anon_const) => {
|
||||
self.visit_node_id(e.span, anon_const.hir_id);
|
||||
|
||||
let body = self.tcx().hir().body(anon_const.body);
|
||||
self.visit_body(body);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_type_ir = { path = "../rustc_type_ir" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
@ -27,8 +27,8 @@
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::relate::{Relate, TypeRelation};
|
||||
use rustc_middle::ty::{Const, ImplSubject};
|
||||
|
||||
/// Whether we should define opaque types or just treat them opaquely.
|
||||
@ -90,7 +90,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToTrace<'tcx>: Relate<'tcx> + Copy {
|
||||
pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy {
|
||||
fn to_trace(
|
||||
cause: &ObligationCause<'tcx>,
|
||||
a_is_expected: bool,
|
||||
|
@ -58,6 +58,7 @@ use crate::traits::{
|
||||
PredicateObligation,
|
||||
};
|
||||
|
||||
use crate::infer::relate::{self, RelateResult, TypeRelation};
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::{
|
||||
codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
|
||||
@ -71,8 +72,8 @@ use rustc_hir::lang_items::LangItem;
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
|
||||
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::Upcast;
|
||||
use rustc_middle::ty::{
|
||||
self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
|
||||
@ -2686,7 +2687,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
|
||||
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
|
||||
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
|
||||
pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
|
||||
pub fn same_type_modulo_infer<T: relate::Relate<TyCtxt<'tcx>>>(&self, a: T, b: T) -> bool {
|
||||
let (a, b) = self.resolve_vars_if_possible((a, b));
|
||||
SameTypeModuloInfer(self).relate(a, b).is_ok()
|
||||
}
|
||||
@ -2694,7 +2695,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
|
||||
struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'tcx>);
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
|
||||
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameTypeModuloInfer<'_, 'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.0.tcx
|
||||
}
|
||||
@ -2703,10 +2704,10 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
|
||||
"SameTypeModuloInfer"
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: relate::Relate<'tcx>>(
|
||||
fn relate_with_variance<T: relate::Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
_variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> relate::RelateResult<'tcx, T> {
|
||||
@ -2754,7 +2755,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> relate::RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: relate::Relate<'tcx>,
|
||||
T: relate::Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||
}
|
||||
|
@ -21,13 +21,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
sp: Span,
|
||||
body_owner_def_id: DefId,
|
||||
) {
|
||||
use ty::error::TypeError::*;
|
||||
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
|
||||
|
||||
let tcx = self.tcx;
|
||||
|
||||
match err {
|
||||
ArgumentSorts(values, _) | Sorts(values) => {
|
||||
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
|
||||
match (*values.expected.kind(), *values.found.kind()) {
|
||||
(ty::Closure(..), ty::Closure(..)) => {
|
||||
diag.note("no two closures, even if identical, have the same type");
|
||||
@ -483,7 +482,7 @@ impl<T> Trait<T> for X {
|
||||
values.found.kind(),
|
||||
);
|
||||
}
|
||||
CyclicTy(ty) => {
|
||||
TypeError::CyclicTy(ty) => {
|
||||
// Watch out for various cases of cyclic types and try to explain.
|
||||
if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() {
|
||||
diag.note(
|
||||
@ -494,7 +493,7 @@ impl<T> Trait<T> for X {
|
||||
);
|
||||
}
|
||||
}
|
||||
TargetFeatureCast(def_id) => {
|
||||
TypeError::TargetFeatureCast(def_id) => {
|
||||
let target_spans = tcx.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
|
||||
diag.note(
|
||||
"functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
|
||||
|
@ -1,9 +1,6 @@
|
||||
pub use at::DefineOpaqueTypes;
|
||||
pub use freshen::TypeFreshener;
|
||||
pub use lexical_region_resolve::RegionResolutionError;
|
||||
pub use relate::combine::CombineFields;
|
||||
pub use relate::combine::ObligationEmittingRelation;
|
||||
pub use relate::StructurallyRelateAliases;
|
||||
pub use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
pub use rustc_middle::ty::IntVarValue;
|
||||
pub use BoundRegionConversionTime::*;
|
||||
@ -11,6 +8,7 @@ pub use RegionVariableOrigin::*;
|
||||
pub use SubregionOrigin::*;
|
||||
pub use ValuePairs::*;
|
||||
|
||||
use crate::infer::relate::{CombineFields, RelateResult};
|
||||
use crate::traits::{
|
||||
self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
|
||||
};
|
||||
@ -39,7 +37,6 @@ use rustc_middle::traits::select;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
|
||||
@ -62,7 +59,7 @@ pub mod opaque_types;
|
||||
pub mod outlives;
|
||||
mod projection;
|
||||
pub mod region_constraints;
|
||||
mod relate;
|
||||
pub mod relate;
|
||||
pub mod resolve;
|
||||
pub(crate) mod snapshot;
|
||||
pub mod type_variable;
|
||||
|
@ -1,15 +1,12 @@
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
error::TypeError,
|
||||
relate::{self, Relate, RelateResult, TypeRelation},
|
||||
Ty, TyCtxt,
|
||||
};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
use crate::infer::region_constraints::VerifyIfEq;
|
||||
use crate::infer::relate::{self as relate, Relate, RelateResult, TypeRelation};
|
||||
|
||||
/// Given a "verify-if-eq" type test like:
|
||||
///
|
||||
@ -135,7 +132,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
|
||||
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx> {
|
||||
fn tag(&self) -> &'static str {
|
||||
"MatchAgainstHigherRankedOutlives"
|
||||
}
|
||||
@ -145,10 +142,10 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_: ty::VarianceDiagInfo<'tcx>,
|
||||
_: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
@ -208,7 +205,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
|
||||
value: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.pattern_depth.shift_in(1);
|
||||
let result = Ok(pattern.rebind(self.relate(pattern.skip_binder(), value.skip_binder())?));
|
||||
|
@ -1,11 +1,11 @@
|
||||
use super::*;
|
||||
use crate::infer::relate::RelateResult;
|
||||
use crate::infer::snapshot::CombinedSnapshot;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph};
|
||||
use rustc_index::Idx;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
|
||||
impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
/// Searches new universes created during `snapshot`, looking for
|
||||
@ -276,7 +276,7 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> {
|
||||
other_region: ty::Region<'tcx>,
|
||||
) -> TypeError<'tcx> {
|
||||
debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
|
||||
TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
|
||||
TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound, other_region)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::ty::error::TypeError;
|
||||
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use crate::ty::{self, InferConst, Ty, TyCtxt};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::{structurally_relate_tys, Relate, RelateResult, TypeRelation};
|
||||
use crate::infer::relate;
|
||||
|
||||
/// A type "A" *matches* "B" if the fresh types in B could be
|
||||
/// instantiated with values so as to make it equal to A. Matching is
|
||||
/// intended to be used only on freshened types, and it basically
|
||||
@ -29,7 +31,7 @@ impl<'tcx> MatchAgainstFreshVars<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
|
||||
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
|
||||
fn tag(&self) -> &'static str {
|
||||
"MatchAgainstFreshVars"
|
||||
}
|
||||
@ -38,10 +40,10 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
_: ty::Variance,
|
||||
_: ty::VarianceDiagInfo<'tcx>,
|
||||
_: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
@ -72,12 +74,12 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
|
||||
) => Ok(a),
|
||||
|
||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
||||
Err(TypeError::Sorts(relate::expected_found(a, b)))
|
||||
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
||||
}
|
||||
|
||||
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)),
|
||||
|
||||
_ => relate::structurally_relate_tys(self, a, b),
|
||||
_ => structurally_relate_tys(self, a, b),
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +99,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
|
||||
}
|
||||
|
||||
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
|
||||
return Err(TypeError::ConstMismatch(relate::expected_found(a, b)));
|
||||
return Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b)));
|
||||
}
|
||||
|
||||
_ => {}
|
||||
@ -112,7 +114,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||
}
|
@ -22,12 +22,13 @@ use super::glb::Glb;
|
||||
use super::lub::Lub;
|
||||
use super::type_relating::TypeRelating;
|
||||
use super::StructurallyRelateAliases;
|
||||
use super::{RelateResult, TypeRelation};
|
||||
use crate::infer::relate;
|
||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::infer::unify_key::EffectVarValue;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
|
||||
use rustc_middle::ty::{IntType, UintType};
|
||||
use rustc_span::Span;
|
||||
@ -121,7 +122,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
|
||||
match relation.structurally_relate_aliases() {
|
||||
StructurallyRelateAliases::Yes => {
|
||||
ty::relate::structurally_relate_tys(relation, a, b)
|
||||
relate::structurally_relate_tys(relation, a, b)
|
||||
}
|
||||
StructurallyRelateAliases::No => {
|
||||
relation.register_type_relate_obligation(a, b);
|
||||
@ -132,7 +133,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
|
||||
// All other cases of inference are errors
|
||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
||||
Err(TypeError::Sorts(ty::relate::expected_found(a, b)))
|
||||
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
||||
}
|
||||
|
||||
// During coherence, opaque types should be treated as *possibly*
|
||||
@ -144,7 +145,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
_ => ty::relate::structurally_relate_tys(relation, a, b),
|
||||
_ => relate::structurally_relate_tys(relation, a, b),
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,11 +235,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
Ok(b)
|
||||
}
|
||||
StructurallyRelateAliases::Yes => {
|
||||
ty::relate::structurally_relate_consts(relation, a, b)
|
||||
relate::structurally_relate_consts(relation, a, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => ty::relate::structurally_relate_consts(relation, a, b),
|
||||
_ => relate::structurally_relate_consts(relation, a, b),
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +304,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
|
||||
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<TyCtxt<'tcx>> {
|
||||
fn span(&self) -> Span;
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||
|
@ -1,15 +1,16 @@
|
||||
use std::mem;
|
||||
|
||||
use super::StructurallyRelateAliases;
|
||||
use super::{ObligationEmittingRelation, Relate, RelateResult, TypeRelation};
|
||||
use crate::infer::relate;
|
||||
use crate::infer::type_variable::TypeVariableValue;
|
||||
use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
|
||||
use crate::infer::{InferCtxt, RegionVariableOrigin};
|
||||
use rustc_data_structures::sso::SsoHashMap;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::infer::unify_key::ConstVariableValue;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::visit::MaxUniverse;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{AliasRelationDirection, InferConst, Term, TypeVisitable, TypeVisitableExt};
|
||||
@ -228,7 +229,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
|
||||
/// Attempts to generalize `source_term` for the type variable `target_vid`.
|
||||
/// This checks for cycles -- that is, whether `source_term` references `target_vid`.
|
||||
fn generalize<T: Into<Term<'tcx>> + Relate<'tcx>>(
|
||||
fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
span: Span,
|
||||
structurally_relate_aliases: StructurallyRelateAliases,
|
||||
@ -395,7 +396,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
@ -430,10 +431,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, variance, b), ret)]
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
@ -695,7 +696,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
_: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
let result = self.relate(a.skip_binder(), a.skip_binder())?;
|
||||
Ok(a.rebind(result))
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Greatest lower bound. See [`lattice`].
|
||||
|
||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
use super::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -21,7 +21,7 @@ impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
||||
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
|
||||
fn tag(&self) -> &'static str {
|
||||
"Glb"
|
||||
}
|
||||
@ -30,10 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
||||
self.fields.tcx()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
@ -81,7 +81,7 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
// GLB of a binder and itself is just itself
|
||||
if a == b {
|
||||
|
@ -1,10 +1,10 @@
|
||||
//! Helper routines for higher-ranked things. See the `doc` module at
|
||||
//! the end of the file for details.
|
||||
|
||||
use super::RelateResult;
|
||||
use crate::infer::snapshot::CombinedSnapshot;
|
||||
use crate::infer::InferCtxt;
|
||||
use rustc_middle::ty::fold::FnMutDelegate;
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
|
@ -21,7 +21,7 @@ use super::combine::ObligationEmittingRelation;
|
||||
use crate::infer::{DefineOpaqueTypes, InferCtxt};
|
||||
use crate::traits::ObligationCause;
|
||||
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
use super::RelateResult;
|
||||
use rustc_middle::ty::TyVar;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
|
@ -6,7 +6,7 @@ use super::StructurallyRelateAliases;
|
||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
|
||||
use crate::traits::{ObligationCause, PredicateObligations};
|
||||
|
||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
use super::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -21,7 +21,7 @@ impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
|
||||
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
|
||||
fn tag(&self) -> &'static str {
|
||||
"Lub"
|
||||
}
|
||||
@ -30,10 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
|
||||
self.fields.tcx()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
@ -81,7 +81,7 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
// LUB of a binder and itself is just itself
|
||||
if a == b {
|
||||
|
@ -1,6 +1,14 @@
|
||||
//! This module contains the definitions of most `TypeRelation`s in the type system
|
||||
//! (except for some relations used for diagnostics and heuristics in the compiler).
|
||||
//! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc).
|
||||
|
||||
pub use rustc_middle::ty::relate::*;
|
||||
|
||||
pub use self::_match::MatchAgainstFreshVars;
|
||||
pub use self::combine::CombineFields;
|
||||
pub use self::combine::ObligationEmittingRelation;
|
||||
|
||||
pub mod _match;
|
||||
pub(super) mod combine;
|
||||
mod generalize;
|
||||
mod glb;
|
||||
@ -8,15 +16,3 @@ mod higher_ranked;
|
||||
mod lattice;
|
||||
mod lub;
|
||||
mod type_relating;
|
||||
|
||||
/// Whether aliases should be related structurally or not. Used
|
||||
/// to adjust the behavior of generalization and combine.
|
||||
///
|
||||
/// This should always be `No` unless in a few special-cases when
|
||||
/// instantiating canonical responses and in the new solver. Each
|
||||
/// such case should have a comment explaining why it is used.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum StructurallyRelateAliases {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
use super::combine::CombineFields;
|
||||
use crate::infer::BoundRegionConversionTime::HigherRankedType;
|
||||
use crate::infer::{
|
||||
DefineOpaqueTypes, ObligationEmittingRelation, StructurallyRelateAliases, SubregionOrigin,
|
||||
};
|
||||
use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
|
||||
use rustc_middle::ty::relate::{
|
||||
relate_args_invariantly, relate_args_with_variances, Relate, RelateResult, TypeRelation,
|
||||
use super::{
|
||||
relate_args_invariantly, relate_args_with_variances, ObligationEmittingRelation, Relate,
|
||||
RelateResult, StructurallyRelateAliases, TypeRelation,
|
||||
};
|
||||
use rustc_middle::ty::TyVar;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
@ -29,7 +28,7 @@ impl<'combine, 'infcx, 'tcx> TypeRelating<'combine, 'infcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
|
||||
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
|
||||
fn tag(&self) -> &'static str {
|
||||
"TypeRelating"
|
||||
}
|
||||
@ -56,10 +55,10 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
_info: ty::VarianceDiagInfo<'tcx>,
|
||||
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
@ -226,7 +225,7 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
if a == b {
|
||||
// Do nothing
|
||||
|
@ -51,7 +51,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::intravisit::FnKind as HirFnKind;
|
||||
use rustc_hir::{Body, FnDecl, GenericParamKind, Node, PatKind, PredicateOrigin};
|
||||
use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
@ -1423,11 +1423,20 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
|
||||
self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true);
|
||||
}
|
||||
|
||||
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
|
||||
if matches!(cx.tcx.parent_hir_node(field.hir_id), Node::Variant(_)) {
|
||||
return;
|
||||
}
|
||||
self.perform_lint(cx, "field", field.def_id, field.vis_span, false);
|
||||
fn check_field_def(&mut self, _cx: &LateContext<'_>, _field: &hir::FieldDef<'_>) {
|
||||
// - If an ADT definition is reported then we don't need to check fields
|
||||
// (as it would add unnecessary complexity to the source code, the struct
|
||||
// definition is in the immediate proximity to give the "real" visibility).
|
||||
// - If an ADT is not reported because it's not `pub` - we don't need to
|
||||
// check fields.
|
||||
// - If an ADT is not reported because it's reachable - we also don't need
|
||||
// to check fields because then they are reachable by construction if they
|
||||
// are pub.
|
||||
//
|
||||
// Therefore in no case we check the fields.
|
||||
//
|
||||
// cf. https://github.com/rust-lang/rust/pull/126013#issuecomment-2152839205
|
||||
// cf. https://github.com/rust-lang/rust/pull/126040#issuecomment-2152944506
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
|
||||
|
@ -581,7 +581,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
||||
self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib),
|
||||
hash,
|
||||
extra_filename,
|
||||
false, // is_host
|
||||
path_kind,
|
||||
);
|
||||
|
||||
|
@ -222,7 +222,6 @@ use rustc_data_structures::owned_slice::slice_owned;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_errors::{DiagArgValue, IntoDiagArg};
|
||||
use rustc_fs_util::try_canonicalize;
|
||||
use rustc_session::config;
|
||||
use rustc_session::cstore::CrateSource;
|
||||
use rustc_session::filesearch::FileSearch;
|
||||
use rustc_session::search_paths::PathKind;
|
||||
@ -309,7 +308,6 @@ impl<'a> CrateLocator<'a> {
|
||||
is_rlib: bool,
|
||||
hash: Option<Svh>,
|
||||
extra_filename: Option<&'a str>,
|
||||
is_host: bool,
|
||||
path_kind: PathKind,
|
||||
) -> CrateLocator<'a> {
|
||||
let needs_object_code = sess.opts.output_types.should_codegen();
|
||||
@ -340,17 +338,9 @@ impl<'a> CrateLocator<'a> {
|
||||
},
|
||||
hash,
|
||||
extra_filename,
|
||||
target: if is_host { &sess.host } else { &sess.target },
|
||||
triple: if is_host {
|
||||
TargetTriple::from_triple(config::host_triple())
|
||||
} else {
|
||||
sess.opts.target_triple.clone()
|
||||
},
|
||||
filesearch: if is_host {
|
||||
sess.host_filesearch(path_kind)
|
||||
} else {
|
||||
sess.target_filesearch(path_kind)
|
||||
},
|
||||
target: &sess.target,
|
||||
triple: sess.opts.target_triple.clone(),
|
||||
filesearch: sess.target_filesearch(path_kind),
|
||||
is_proc_macro: false,
|
||||
crate_rejections: CrateRejections::default(),
|
||||
}
|
||||
@ -424,12 +414,18 @@ impl<'a> CrateLocator<'a> {
|
||||
debug!("testing {}", spf.path.display());
|
||||
|
||||
let f = &spf.file_name_str;
|
||||
let (hash, kind) = if f.starts_with(rlib_prefix) && f.ends_with(rlib_suffix) {
|
||||
(&f[rlib_prefix.len()..(f.len() - rlib_suffix.len())], CrateFlavor::Rlib)
|
||||
} else if f.starts_with(rmeta_prefix) && f.ends_with(rmeta_suffix) {
|
||||
(&f[rmeta_prefix.len()..(f.len() - rmeta_suffix.len())], CrateFlavor::Rmeta)
|
||||
} else if f.starts_with(dylib_prefix) && f.ends_with(dylib_suffix.as_ref()) {
|
||||
(&f[dylib_prefix.len()..(f.len() - dylib_suffix.len())], CrateFlavor::Dylib)
|
||||
let (hash, kind) = if let Some(f) = f.strip_prefix(rlib_prefix)
|
||||
&& let Some(f) = f.strip_suffix(rlib_suffix)
|
||||
{
|
||||
(f, CrateFlavor::Rlib)
|
||||
} else if let Some(f) = f.strip_prefix(rmeta_prefix)
|
||||
&& let Some(f) = f.strip_suffix(rmeta_suffix)
|
||||
{
|
||||
(f, CrateFlavor::Rmeta)
|
||||
} else if let Some(f) = f.strip_prefix(dylib_prefix)
|
||||
&& let Some(f) = f.strip_suffix(dylib_suffix.as_ref())
|
||||
{
|
||||
(f, CrateFlavor::Dylib)
|
||||
} else {
|
||||
if f.starts_with(staticlib_prefix) && f.ends_with(staticlib_suffix.as_ref()) {
|
||||
self.crate_rejections.via_kind.push(CrateMismatch {
|
||||
|
@ -28,7 +28,6 @@ rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
|
@ -62,7 +62,7 @@ macro_rules! arena_types {
|
||||
[] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
|
||||
[] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
|
||||
[] canonical_goal_evaluation:
|
||||
rustc_next_trait_solver::solve::inspect::CanonicalGoalEvaluationStep<
|
||||
rustc_type_ir::solve::inspect::CanonicalGoalEvaluationStep<
|
||||
rustc_middle::ty::TyCtxt<'tcx>
|
||||
>,
|
||||
[] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::hir::ModuleItems;
|
||||
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||
use crate::query::LocalCrate;
|
||||
@ -256,26 +254,13 @@ impl<'hir> Map<'hir> {
|
||||
|
||||
/// Given a `LocalDefId`, returns the `BodyId` associated with it,
|
||||
/// if the node is a body owner, otherwise returns `None`.
|
||||
pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<Cow<'hir, Body<'hir>>> {
|
||||
Some(match self.tcx.def_kind(id) {
|
||||
// Inline consts do not have bodies of their own, so create one to make the follow-up logic simpler.
|
||||
DefKind::InlineConst => {
|
||||
let e = self.expect_expr(self.tcx.local_def_id_to_hir_id(id));
|
||||
Cow::Owned(Body {
|
||||
params: &[],
|
||||
value: match e.kind {
|
||||
ExprKind::ConstBlock(body) => body,
|
||||
_ => span_bug!(e.span, "InlineConst was not a ConstBlock: {e:#?}"),
|
||||
},
|
||||
})
|
||||
}
|
||||
_ => Cow::Borrowed(self.body(self.tcx.hir_node_by_def_id(id).body_id()?)),
|
||||
})
|
||||
pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<&'hir Body<'hir>> {
|
||||
Some(self.body(self.tcx.hir_node_by_def_id(id).body_id()?))
|
||||
}
|
||||
|
||||
/// Given a body owner's id, returns the `BodyId` associated with it.
|
||||
#[track_caller]
|
||||
pub fn body_owned_by(self, id: LocalDefId) -> Cow<'hir, Body<'hir>> {
|
||||
pub fn body_owned_by(self, id: LocalDefId) -> &'hir Body<'hir> {
|
||||
self.maybe_body_owned_by(id).unwrap_or_else(|| {
|
||||
let hir_id = self.tcx.local_def_id_to_hir_id(id);
|
||||
span_bug!(
|
||||
@ -338,7 +323,7 @@ impl<'hir> Map<'hir> {
|
||||
|
||||
/// Returns an iterator of the `DefId`s for all body-owners in this
|
||||
/// crate. If you would prefer to iterate over the bodies
|
||||
/// themselves, you can do `self.hir().krate().owners.iter()`.
|
||||
/// themselves, you can do `self.hir().krate().body_ids.iter()`.
|
||||
#[inline]
|
||||
pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
|
||||
self.tcx.hir_crate_items(()).body_owners.iter().copied()
|
||||
@ -525,17 +510,7 @@ impl<'hir> Map<'hir> {
|
||||
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
|
||||
/// Used exclusively for diagnostics, to avoid suggestion function calls.
|
||||
pub fn is_inside_const_context(self, hir_id: HirId) -> bool {
|
||||
for (_, node) in self.parent_iter(hir_id) {
|
||||
if let Some((def_id, _)) = node.associated_body() {
|
||||
return self.body_const_context(def_id).is_some();
|
||||
}
|
||||
if let Node::Expr(e) = node {
|
||||
if let ExprKind::ConstBlock(_) = e.kind {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
self.body_const_context(self.enclosing_body_owner(hir_id)).is_some()
|
||||
}
|
||||
|
||||
/// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
|
||||
@ -918,6 +893,7 @@ impl<'hir> Map<'hir> {
|
||||
Node::Variant(variant) => variant.span,
|
||||
Node::Field(field) => field.span,
|
||||
Node::AnonConst(constant) => constant.span,
|
||||
Node::ConstBlock(constant) => self.body(constant.body).value.span,
|
||||
Node::Expr(expr) => expr.span,
|
||||
Node::ExprField(field) => field.span,
|
||||
Node::Stmt(stmt) => stmt.span,
|
||||
@ -1187,6 +1163,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
||||
format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
|
||||
}
|
||||
Node::AnonConst(_) => node_str("const"),
|
||||
Node::ConstBlock(_) => node_str("const"),
|
||||
Node::Expr(_) => node_str("expr"),
|
||||
Node::ExprField(_) => node_str("expr field"),
|
||||
Node::Stmt(_) => node_str("stmt"),
|
||||
@ -1336,6 +1313,11 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
|
||||
intravisit::walk_anon_const(self, c)
|
||||
}
|
||||
|
||||
fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
|
||||
self.body_owners.push(c.def_id);
|
||||
intravisit::walk_inline_const(self, c)
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
|
||||
if let ExprKind::Closure(closure) = ex.kind {
|
||||
self.body_owners.push(closure.def_id);
|
||||
|
@ -196,6 +196,11 @@ impl<Prov> Scalar<Prov> {
|
||||
Self::from_int(i, Size::from_bits(64))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_i128(i: i128) -> Self {
|
||||
Self::from_int(i, Size::from_bits(128))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
|
||||
Self::from_int(i, cx.data_layout().pointer_size)
|
||||
|
@ -5,9 +5,9 @@ use rustc_data_structures::base_n::BaseNString;
|
||||
use rustc_data_structures::base_n::ToBaseN;
|
||||
use rustc_data_structures::base_n::CASE_INSENSITIVE;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher, ToStableHashKey};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc_hir::ItemId;
|
||||
use rustc_index::Idx;
|
||||
@ -241,7 +241,17 @@ impl<'tcx> fmt::Display for MonoItem<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
impl ToStableHashKey<StableHashingContext<'_>> for MonoItem<'_> {
|
||||
type KeyType = Fingerprint;
|
||||
|
||||
fn to_stable_hash_key(&self, hcx: &StableHashingContext<'_>) -> Self::KeyType {
|
||||
let mut hasher = StableHasher::new();
|
||||
self.hash_stable(&mut hcx.clone(), &mut hasher);
|
||||
hasher.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable)]
|
||||
pub struct CodegenUnit<'tcx> {
|
||||
/// A name for this CGU. Incremental compilation requires that
|
||||
/// name be unique amongst **all** crates. Therefore, it should
|
||||
@ -430,38 +440,19 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
let CodegenUnit {
|
||||
ref items,
|
||||
name,
|
||||
// The size estimate is not relevant to the hash
|
||||
size_estimate: _,
|
||||
primary: _,
|
||||
is_code_coverage_dead_code_cgu,
|
||||
} = *self;
|
||||
impl ToStableHashKey<StableHashingContext<'_>> for CodegenUnit<'_> {
|
||||
type KeyType = String;
|
||||
|
||||
name.hash_stable(hcx, hasher);
|
||||
is_code_coverage_dead_code_cgu.hash_stable(hcx, hasher);
|
||||
|
||||
let mut items: Vec<(Fingerprint, _)> = items
|
||||
.iter()
|
||||
.map(|(mono_item, &attrs)| {
|
||||
let mut hasher = StableHasher::new();
|
||||
mono_item.hash_stable(hcx, &mut hasher);
|
||||
let mono_item_fingerprint = hasher.finish();
|
||||
(mono_item_fingerprint, attrs)
|
||||
})
|
||||
.collect();
|
||||
|
||||
items.sort_unstable_by_key(|i| i.0);
|
||||
items.hash_stable(hcx, hasher);
|
||||
fn to_stable_hash_key(&self, _: &StableHashingContext<'_>) -> Self::KeyType {
|
||||
// Codegen unit names are conceptually required to be stable across
|
||||
// compilation session so that object file names match up.
|
||||
self.name.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CodegenUnitNameBuilder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cache: FxHashMap<CrateNum, String>,
|
||||
cache: UnordMap<CrateNum, String>,
|
||||
}
|
||||
|
||||
impl<'tcx> CodegenUnitNameBuilder<'tcx> {
|
||||
|
@ -32,7 +32,7 @@ use std::hash::{Hash, Hasher};
|
||||
|
||||
pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
|
||||
// FIXME: Remove this import and import via `solve::`
|
||||
pub use rustc_next_trait_solver::solve::BuiltinImplSource;
|
||||
pub use rustc_type_ir::solve::BuiltinImplSource;
|
||||
|
||||
/// Depending on the stage of compilation, we want projection to be
|
||||
/// more or less conservative.
|
||||
|
@ -7,13 +7,12 @@
|
||||
|
||||
use crate::error::DropCheckOverflow;
|
||||
use crate::infer::canonical::{Canonical, QueryResponse};
|
||||
use crate::ty::error::TypeError;
|
||||
use crate::ty::GenericArg;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
|
||||
use rustc_span::Span;
|
||||
// FIXME: Remove this import and import via `traits::solve`.
|
||||
pub use rustc_next_trait_solver::solve::NoSolution;
|
||||
pub use rustc_type_ir::solve::NoSolution;
|
||||
|
||||
pub mod type_op {
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
@ -91,12 +90,6 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
|
||||
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
|
||||
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
|
||||
|
||||
impl<'tcx> From<TypeError<'tcx>> for NoSolution {
|
||||
fn from(_: TypeError<'tcx>) -> NoSolution {
|
||||
NoSolution
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct DropckOutlivesResult<'tcx> {
|
||||
pub kinds: Vec<GenericArg<'tcx>>,
|
||||
|
@ -1,8 +1,8 @@
|
||||
use rustc_ast_ir::try_visit;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
|
||||
use rustc_next_trait_solver as ir;
|
||||
pub use rustc_next_trait_solver::solve::*;
|
||||
use rustc_type_ir as ir;
|
||||
pub use rustc_type_ir::solve::*;
|
||||
|
||||
use crate::infer::canonical::QueryRegionConstraints;
|
||||
use crate::ty::{
|
||||
|
@ -200,6 +200,12 @@ impl<'tcx> AdtDef<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
|
||||
fn def_id(self) -> DefId {
|
||||
self.did()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
|
||||
pub enum AdtKind {
|
||||
Struct,
|
||||
|
@ -149,6 +149,10 @@ impl<'tcx> Const<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
||||
fn try_to_target_usize(self, interner: TyCtxt<'tcx>) -> Option<u64> {
|
||||
self.try_to_target_usize(interner)
|
||||
}
|
||||
|
||||
fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
|
||||
Const::new_infer(tcx, infer)
|
||||
}
|
||||
@ -168,6 +172,10 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
||||
fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
|
||||
Const::new_unevaluated(interner, uv)
|
||||
}
|
||||
|
||||
fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self {
|
||||
Const::new_expr(interner, expr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Const<'tcx> {
|
||||
|
@ -69,6 +69,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
use rustc_type_ir::TyKind::*;
|
||||
use rustc_type_ir::WithCachedTypeInfo;
|
||||
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
|
||||
@ -135,9 +136,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
type ParamEnv = ty::ParamEnv<'tcx>;
|
||||
type Predicate = Predicate<'tcx>;
|
||||
type Clause = Clause<'tcx>;
|
||||
|
||||
type Clauses = ty::Clauses<'tcx>;
|
||||
|
||||
fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T {
|
||||
self.expand_abstract_consts(t)
|
||||
}
|
||||
|
||||
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
|
||||
self.mk_canonical_var_infos(infos)
|
||||
}
|
||||
@ -148,6 +152,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
self.generics_of(def_id)
|
||||
}
|
||||
|
||||
type VariancesOf = &'tcx [ty::Variance];
|
||||
|
||||
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
|
||||
self.variances_of(def_id)
|
||||
}
|
||||
|
||||
fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
|
||||
self.type_of(def_id)
|
||||
}
|
||||
@ -205,7 +215,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
self.mk_args(args)
|
||||
}
|
||||
|
||||
fn mk_args_from_iter(self, args: impl Iterator<Item = Self::GenericArg>) -> Self::GenericArgs {
|
||||
fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: CollectAndApply<Self::GenericArg, Self::GenericArgs>,
|
||||
{
|
||||
self.mk_args_from_iter(args)
|
||||
}
|
||||
|
||||
@ -224,6 +238,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
self.arena.alloc(step)
|
||||
}
|
||||
|
||||
fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: CollectAndApply<Self::Ty, Self::Tys>,
|
||||
{
|
||||
self.mk_type_list_from_iter(args)
|
||||
}
|
||||
|
||||
fn parent(self, def_id: Self::DefId) -> Self::DefId {
|
||||
self.parent(def_id)
|
||||
}
|
||||
@ -231,6 +253,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
fn recursion_limit(self) -> usize {
|
||||
self.recursion_limit().0
|
||||
}
|
||||
|
||||
type Features = &'tcx rustc_feature::Features;
|
||||
|
||||
fn features(self) -> Self::Features {
|
||||
self.features()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
|
||||
@ -249,6 +277,12 @@ impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_feature::Features {
|
||||
fn generic_const_exprs(self) -> bool {
|
||||
self.generic_const_exprs
|
||||
}
|
||||
}
|
||||
|
||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||
|
||||
pub struct CtxtInterners<'tcx> {
|
||||
@ -740,7 +774,6 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
|
||||
1,
|
||||
),
|
||||
bodies,
|
||||
has_inline_consts: false,
|
||||
})));
|
||||
self.feed_owner_id().hir_attrs(attrs);
|
||||
}
|
||||
|
@ -1,89 +1,26 @@
|
||||
use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
|
||||
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
|
||||
use rustc_errors::pluralize;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_macros::extension;
|
||||
pub use rustc_type_ir::error::ExpectedFound;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
|
||||
pub struct ExpectedFound<T> {
|
||||
pub expected: T,
|
||||
pub found: T,
|
||||
}
|
||||
pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
|
||||
|
||||
impl<T> ExpectedFound<T> {
|
||||
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
|
||||
if a_is_expected {
|
||||
ExpectedFound { expected: a, found: b }
|
||||
} else {
|
||||
ExpectedFound { expected: b, found: a }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Data structures used in type unification
|
||||
#[derive(Copy, Clone, Debug, TypeVisitable, PartialEq, Eq)]
|
||||
#[rustc_pass_by_value]
|
||||
pub enum TypeError<'tcx> {
|
||||
Mismatch,
|
||||
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
||||
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
|
||||
SafetyMismatch(ExpectedFound<hir::Safety>),
|
||||
AbiMismatch(ExpectedFound<abi::Abi>),
|
||||
Mutability,
|
||||
ArgumentMutability(usize),
|
||||
TupleSize(ExpectedFound<usize>),
|
||||
FixedArraySize(ExpectedFound<u64>),
|
||||
ArgCount,
|
||||
FieldMisMatch(Symbol, Symbol),
|
||||
|
||||
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
|
||||
RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
|
||||
RegionsPlaceholderMismatch,
|
||||
|
||||
Sorts(ExpectedFound<Ty<'tcx>>),
|
||||
ArgumentSorts(ExpectedFound<Ty<'tcx>>, usize),
|
||||
Traits(ExpectedFound<DefId>),
|
||||
VariadicMismatch(ExpectedFound<bool>),
|
||||
|
||||
/// Instantiating a type variable with the given type would have
|
||||
/// created a cycle (because it appears somewhere within that
|
||||
/// type).
|
||||
CyclicTy(Ty<'tcx>),
|
||||
CyclicConst(ty::Const<'tcx>),
|
||||
ProjectionMismatched(ExpectedFound<DefId>),
|
||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>),
|
||||
ConstMismatch(ExpectedFound<ty::Const<'tcx>>),
|
||||
|
||||
IntrinsicCast,
|
||||
/// Safe `#[target_feature]` functions are not assignable to safe function pointers.
|
||||
TargetFeatureCast(DefId),
|
||||
}
|
||||
|
||||
impl TypeError<'_> {
|
||||
pub fn involves_regions(self) -> bool {
|
||||
match self {
|
||||
TypeError::RegionsDoesNotOutlive(_, _)
|
||||
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
|
||||
| TypeError::RegionsPlaceholderMismatch => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Explains the source of a type err in a short, human readable way. This is meant to be placed
|
||||
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
|
||||
/// afterwards to present additional details, particularly when it comes to lifetime-related
|
||||
/// errors.
|
||||
/// Explains the source of a type err in a short, human readable way.
|
||||
/// This is meant to be placed in parentheses after some larger message.
|
||||
/// You should also invoke `note_and_explain_type_err()` afterwards
|
||||
/// to present additional details, particularly when it comes to lifetime-
|
||||
/// related errors.
|
||||
#[extension(pub trait TypeErrorToStringExt<'tcx>)]
|
||||
impl<'tcx> TypeError<'tcx> {
|
||||
pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
use self::TypeError::*;
|
||||
fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
fn report_maybe_different(expected: &str, found: &str) -> String {
|
||||
// A naive approach to making sure that we're not reporting silly errors such as:
|
||||
// (expected closure, found closure).
|
||||
@ -95,24 +32,26 @@ impl<'tcx> TypeError<'tcx> {
|
||||
}
|
||||
|
||||
match self {
|
||||
CyclicTy(_) => "cyclic type of infinite size".into(),
|
||||
CyclicConst(_) => "encountered a self-referencing constant".into(),
|
||||
Mismatch => "types differ".into(),
|
||||
ConstnessMismatch(values) => {
|
||||
TypeError::CyclicTy(_) => "cyclic type of infinite size".into(),
|
||||
TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(),
|
||||
TypeError::Mismatch => "types differ".into(),
|
||||
TypeError::ConstnessMismatch(values) => {
|
||||
format!("expected {} bound, found {} bound", values.expected, values.found).into()
|
||||
}
|
||||
PolarityMismatch(values) => {
|
||||
TypeError::PolarityMismatch(values) => {
|
||||
format!("expected {} polarity, found {} polarity", values.expected, values.found)
|
||||
.into()
|
||||
}
|
||||
SafetyMismatch(values) => {
|
||||
TypeError::SafetyMismatch(values) => {
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found).into()
|
||||
}
|
||||
AbiMismatch(values) => {
|
||||
TypeError::AbiMismatch(values) => {
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found).into()
|
||||
}
|
||||
ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
|
||||
TupleSize(values) => format!(
|
||||
TypeError::ArgumentMutability(_) | TypeError::Mutability => {
|
||||
"types differ in mutability".into()
|
||||
}
|
||||
TypeError::TupleSize(values) => format!(
|
||||
"expected a tuple with {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
@ -120,7 +59,7 @@ impl<'tcx> TypeError<'tcx> {
|
||||
pluralize!(values.found)
|
||||
)
|
||||
.into(),
|
||||
FixedArraySize(values) => format!(
|
||||
TypeError::FixedArraySize(values) => format!(
|
||||
"expected an array with a fixed size of {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
@ -128,20 +67,21 @@ impl<'tcx> TypeError<'tcx> {
|
||||
pluralize!(values.found)
|
||||
)
|
||||
.into(),
|
||||
ArgCount => "incorrect number of function parameters".into(),
|
||||
FieldMisMatch(adt, field) => format!("field type mismatch: {adt}.{field}").into(),
|
||||
RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
|
||||
TypeError::ArgCount => "incorrect number of function parameters".into(),
|
||||
TypeError::RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
|
||||
// Actually naming the region here is a bit confusing because context is lacking
|
||||
RegionsInsufficientlyPolymorphic(..) => {
|
||||
TypeError::RegionsInsufficientlyPolymorphic(..) => {
|
||||
"one type is more general than the other".into()
|
||||
}
|
||||
RegionsPlaceholderMismatch => "one type is more general than the other".into(),
|
||||
ArgumentSorts(values, _) | Sorts(values) => {
|
||||
TypeError::RegionsPlaceholderMismatch => {
|
||||
"one type is more general than the other".into()
|
||||
}
|
||||
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
|
||||
let expected = values.expected.sort_string(tcx);
|
||||
let found = values.found.sort_string(tcx);
|
||||
report_maybe_different(&expected, &found).into()
|
||||
}
|
||||
Traits(values) => {
|
||||
TypeError::Traits(values) => {
|
||||
let (mut expected, mut found) = with_forced_trimmed_paths!((
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found),
|
||||
@ -153,59 +93,34 @@ impl<'tcx> TypeError<'tcx> {
|
||||
report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
|
||||
.into()
|
||||
}
|
||||
VariadicMismatch(ref values) => format!(
|
||||
TypeError::VariadicMismatch(ref values) => format!(
|
||||
"expected {} fn, found {} function",
|
||||
if values.expected { "variadic" } else { "non-variadic" },
|
||||
if values.found { "variadic" } else { "non-variadic" }
|
||||
)
|
||||
.into(),
|
||||
ProjectionMismatched(ref values) => format!(
|
||||
TypeError::ProjectionMismatched(ref values) => format!(
|
||||
"expected `{}`, found `{}`",
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found)
|
||||
)
|
||||
.into(),
|
||||
ExistentialMismatch(ref values) => report_maybe_different(
|
||||
TypeError::ExistentialMismatch(ref values) => report_maybe_different(
|
||||
&format!("trait `{}`", values.expected),
|
||||
&format!("trait `{}`", values.found),
|
||||
)
|
||||
.into(),
|
||||
ConstMismatch(ref values) => {
|
||||
TypeError::ConstMismatch(ref values) => {
|
||||
format!("expected `{}`, found `{}`", values.expected, values.found).into()
|
||||
}
|
||||
IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
|
||||
TargetFeatureCast(_) => {
|
||||
TypeError::IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
|
||||
TypeError::TargetFeatureCast(_) => {
|
||||
"cannot coerce functions with `#[target_feature]` to safe function pointers".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeError<'tcx> {
|
||||
pub fn must_include_note(self) -> bool {
|
||||
use self::TypeError::*;
|
||||
match self {
|
||||
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
|
||||
| PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
|
||||
| ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
|
||||
|
||||
Mutability
|
||||
| ArgumentMutability(_)
|
||||
| TupleSize(_)
|
||||
| ArgCount
|
||||
| FieldMisMatch(..)
|
||||
| RegionsDoesNotOutlive(..)
|
||||
| RegionsInsufficientlyPolymorphic(..)
|
||||
| RegionsPlaceholderMismatch
|
||||
| Traits(_)
|
||||
| ProjectionMismatched(_)
|
||||
| ExistentialMismatch(_)
|
||||
| ConstMismatch(_)
|
||||
| IntrinsicCast => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Ty<'tcx> {
|
||||
pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
match *self.kind() {
|
||||
|
@ -60,6 +60,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{ExpnId, ExpnKind, Span};
|
||||
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
|
||||
pub use rustc_target::abi::{ReprFlags, ReprOptions};
|
||||
pub use rustc_type_ir::relate::VarianceDiagInfo;
|
||||
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||
use tracing::{debug, instrument};
|
||||
pub use vtable::*;
|
||||
@ -114,7 +115,7 @@ pub use self::rvalue_scopes::RvalueScopes;
|
||||
pub use self::sty::{
|
||||
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
|
||||
CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
|
||||
ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
|
||||
ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
pub use self::typeck_results::{
|
||||
@ -122,7 +123,6 @@ pub use self::typeck_results::{
|
||||
TypeckResults, UserType, UserTypeAnnotationIndex,
|
||||
};
|
||||
|
||||
pub mod _match;
|
||||
pub mod abstract_const;
|
||||
pub mod adjustment;
|
||||
pub mod cast;
|
||||
@ -313,38 +313,6 @@ impl Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||
pub enum BoundConstness {
|
||||
/// `Type: Trait`
|
||||
NotConst,
|
||||
/// `Type: const Trait`
|
||||
Const,
|
||||
/// `Type: ~const Trait`
|
||||
///
|
||||
/// Requires resolving to const only when we are in a const context.
|
||||
ConstIfConst,
|
||||
}
|
||||
|
||||
impl BoundConstness {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::NotConst => "",
|
||||
Self::Const => "const",
|
||||
Self::ConstIfConst => "~const",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BoundConstness {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::NotConst => f.write_str("normal"),
|
||||
Self::Const => f.write_str("const"),
|
||||
Self::ConstIfConst => f.write_str("~const"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct ClosureSizeProfileData<'tcx> {
|
||||
|
@ -1,383 +1,54 @@
|
||||
//! Generalized type relating mechanism.
|
||||
//!
|
||||
//! A type relation `R` relates a pair of values `(A, B)`. `A and B` are usually
|
||||
//! types or regions but can be other things. Examples of type relations are
|
||||
//! subtyping, type equality, etc.
|
||||
use std::iter;
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_target::spec::abi;
|
||||
pub use rustc_type_ir::relate::*;
|
||||
|
||||
use crate::ty::error::{ExpectedFound, TypeError};
|
||||
use crate::ty::{
|
||||
self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, GenericArg, GenericArgKind,
|
||||
GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::TypeVisitable;
|
||||
use rustc_target::spec::abi;
|
||||
use std::iter;
|
||||
use tracing::{debug, instrument};
|
||||
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
|
||||
use crate::ty::{self as ty, Ty, TyCtxt};
|
||||
|
||||
use super::Pattern;
|
||||
pub type RelateResult<'tcx, T> = rustc_type_ir::relate::RelateResult<TyCtxt<'tcx>, T>;
|
||||
|
||||
pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
|
||||
|
||||
pub trait TypeRelation<'tcx>: Sized {
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
|
||||
/// Returns a static string we can use for printouts.
|
||||
fn tag(&self) -> &'static str;
|
||||
|
||||
/// Generic relation routine suitable for most anything.
|
||||
fn relate<T: Relate<'tcx>>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> {
|
||||
Relate::relate(self, a, b)
|
||||
}
|
||||
|
||||
/// Relate the two args for the given item. The default
|
||||
/// is to look up the variance for the item and proceed
|
||||
/// accordingly.
|
||||
fn relate_item_args(
|
||||
&mut self,
|
||||
item_def_id: DefId,
|
||||
a_arg: GenericArgsRef<'tcx>,
|
||||
b_arg: GenericArgsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
|
||||
debug!(
|
||||
"relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})",
|
||||
item_def_id, a_arg, b_arg
|
||||
);
|
||||
|
||||
let tcx = self.tcx();
|
||||
let opt_variances = tcx.variances_of(item_def_id);
|
||||
relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true)
|
||||
}
|
||||
|
||||
/// Switch variance for the purpose of relating `a` and `b`.
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
info: ty::VarianceDiagInfo<'tcx>,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T>;
|
||||
|
||||
// Overridable relations. You shouldn't typically call these
|
||||
// directly, instead call `relate()`, which in turn calls
|
||||
// these. This is both more uniform but also allows us to add
|
||||
// additional hooks for other types in the future if needed
|
||||
// without making older code, which called `relate`, obsolete.
|
||||
|
||||
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>;
|
||||
|
||||
fn regions(
|
||||
&mut self,
|
||||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Region<'tcx>>;
|
||||
|
||||
fn consts(
|
||||
&mut self,
|
||||
a: ty::Const<'tcx>,
|
||||
b: ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>>;
|
||||
|
||||
fn binders<T>(
|
||||
&mut self,
|
||||
a: ty::Binder<'tcx, T>,
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
|
||||
where
|
||||
T: Relate<'tcx>;
|
||||
/// Whether aliases should be related structurally or not. Used
|
||||
/// to adjust the behavior of generalization and combine.
|
||||
///
|
||||
/// This should always be `No` unless in a few special-cases when
|
||||
/// instantiating canonical responses and in the new solver. Each
|
||||
/// such case should have a comment explaining why it is used.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum StructurallyRelateAliases {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
pub trait Relate<'tcx>: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: Self,
|
||||
b: Self,
|
||||
) -> RelateResult<'tcx, Self>;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Relate impls
|
||||
|
||||
#[inline]
|
||||
pub fn relate_args_invariantly<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a_arg: GenericArgsRef<'tcx>,
|
||||
b_arg: GenericArgsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
|
||||
relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| {
|
||||
relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn relate_args_with_variances<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
ty_def_id: DefId,
|
||||
variances: &[ty::Variance],
|
||||
a_arg: GenericArgsRef<'tcx>,
|
||||
b_arg: GenericArgsRef<'tcx>,
|
||||
fetch_ty_for_diag: bool,
|
||||
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
|
||||
let tcx = relation.tcx();
|
||||
|
||||
let mut cached_ty = None;
|
||||
let params = iter::zip(a_arg, b_arg).enumerate().map(|(i, (a, b))| {
|
||||
let variance = variances[i];
|
||||
let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
|
||||
let ty =
|
||||
*cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, a_arg));
|
||||
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
|
||||
} else {
|
||||
ty::VarianceDiagInfo::default()
|
||||
};
|
||||
relation.relate_with_variance(variance, variance_info, a, b)
|
||||
});
|
||||
|
||||
tcx.mk_args_from_iter(params)
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::FnSig<'tcx>,
|
||||
b: ty::FnSig<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::FnSig<'tcx>> {
|
||||
let tcx = relation.tcx();
|
||||
|
||||
if a.c_variadic != b.c_variadic {
|
||||
return Err(TypeError::VariadicMismatch(expected_found(a.c_variadic, b.c_variadic)));
|
||||
}
|
||||
let safety = relation.relate(a.safety, b.safety)?;
|
||||
let abi = relation.relate(a.abi, b.abi)?;
|
||||
|
||||
if a.inputs().len() != b.inputs().len() {
|
||||
return Err(TypeError::ArgCount);
|
||||
}
|
||||
|
||||
let inputs_and_output = iter::zip(a.inputs(), b.inputs())
|
||||
.map(|(&a, &b)| ((a, b), false))
|
||||
.chain(iter::once(((a.output(), b.output()), true)))
|
||||
.map(|((a, b), is_output)| {
|
||||
if is_output {
|
||||
relation.relate(a, b)
|
||||
} else {
|
||||
relation.relate_with_variance(
|
||||
ty::Contravariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a,
|
||||
b,
|
||||
)
|
||||
}
|
||||
})
|
||||
.enumerate()
|
||||
.map(|(i, r)| match r {
|
||||
Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
|
||||
Err(TypeError::ArgumentSorts(exp_found, i))
|
||||
}
|
||||
Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
|
||||
Err(TypeError::ArgumentMutability(i))
|
||||
}
|
||||
r => r,
|
||||
});
|
||||
Ok(ty::FnSig {
|
||||
inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
|
||||
c_variadic: a.c_variadic,
|
||||
safety,
|
||||
abi,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::BoundConstness {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
_relation: &mut R,
|
||||
a: ty::BoundConstness,
|
||||
b: ty::BoundConstness,
|
||||
) -> RelateResult<'tcx, ty::BoundConstness> {
|
||||
if a != b { Err(TypeError::ConstnessMismatch(expected_found(a, b))) } else { Ok(a) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for hir::Safety {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
_relation: &mut R,
|
||||
a: hir::Safety,
|
||||
b: hir::Safety,
|
||||
) -> RelateResult<'tcx, hir::Safety> {
|
||||
if a != b { Err(TypeError::SafetyMismatch(expected_found(a, b))) } else { Ok(a) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for abi::Abi {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
_relation: &mut R,
|
||||
a: abi::Abi,
|
||||
b: abi::Abi,
|
||||
) -> RelateResult<'tcx, abi::Abi> {
|
||||
if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(a, b))) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::AliasTy<'tcx>,
|
||||
b: ty::AliasTy<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
|
||||
if a.def_id != b.def_id {
|
||||
Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
|
||||
} else {
|
||||
let args = match a.kind(relation.tcx()) {
|
||||
ty::Opaque => relate_args_with_variances(
|
||||
relation,
|
||||
a.def_id,
|
||||
relation.tcx().variances_of(a.def_id),
|
||||
a.args,
|
||||
b.args,
|
||||
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
|
||||
)?,
|
||||
ty::Projection | ty::Weak | ty::Inherent => {
|
||||
relate_args_invariantly(relation, a.args, b.args)?
|
||||
}
|
||||
};
|
||||
Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::AliasTerm<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::AliasTerm<'tcx>,
|
||||
b: ty::AliasTerm<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::AliasTerm<'tcx>> {
|
||||
if a.def_id != b.def_id {
|
||||
Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
|
||||
} else {
|
||||
let args = match a.kind(relation.tcx()) {
|
||||
ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
|
||||
relation,
|
||||
a.def_id,
|
||||
relation.tcx().variances_of(a.def_id),
|
||||
a.args,
|
||||
b.args,
|
||||
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
|
||||
)?,
|
||||
ty::AliasTermKind::ProjectionTy
|
||||
| ty::AliasTermKind::WeakTy
|
||||
| ty::AliasTermKind::InherentTy
|
||||
| ty::AliasTermKind::UnevaluatedConst
|
||||
| ty::AliasTermKind::ProjectionConst => {
|
||||
relate_args_invariantly(relation, a.args, b.args)?
|
||||
}
|
||||
};
|
||||
Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::ExistentialProjection<'tcx>,
|
||||
b: ty::ExistentialProjection<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
|
||||
if a.def_id != b.def_id {
|
||||
Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
|
||||
} else {
|
||||
let term = relation.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a.term,
|
||||
b.term,
|
||||
)?;
|
||||
let args = relation.relate_with_variance(
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a.args,
|
||||
b.args,
|
||||
)?;
|
||||
Ok(ty::ExistentialProjection { def_id: a.def_id, args, term })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::TraitRef<'tcx>,
|
||||
b: ty::TraitRef<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
|
||||
// Different traits cannot be related.
|
||||
if a.def_id != b.def_id {
|
||||
Err(TypeError::Traits(expected_found(a.def_id, b.def_id)))
|
||||
} else {
|
||||
let args = relate_args_invariantly(relation, a.args, b.args)?;
|
||||
Ok(ty::TraitRef::new(relation.tcx(), a.def_id, args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::ExistentialTraitRef<'tcx>,
|
||||
b: ty::ExistentialTraitRef<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
|
||||
// Different traits cannot be related.
|
||||
if a.def_id != b.def_id {
|
||||
Err(TypeError::Traits(expected_found(a.def_id, b.def_id)))
|
||||
} else {
|
||||
let args = relate_args_invariantly(relation, a.args, b.args)?;
|
||||
Ok(ty::ExistentialTraitRef { def_id: a.def_id, args })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
|
||||
struct CoroutineWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
|
||||
|
||||
impl<'tcx> Relate<'tcx> for CoroutineWitness<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: CoroutineWitness<'tcx>,
|
||||
b: CoroutineWitness<'tcx>,
|
||||
) -> RelateResult<'tcx, CoroutineWitness<'tcx>> {
|
||||
assert_eq!(a.0.len(), b.0.len());
|
||||
let tcx = relation.tcx();
|
||||
let types =
|
||||
tcx.mk_type_list_from_iter(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
|
||||
Ok(CoroutineWitness(types))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ImplSubject<'tcx> {
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::ImplSubject<'tcx> {
|
||||
#[inline]
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: ImplSubject<'tcx>,
|
||||
b: ImplSubject<'tcx>,
|
||||
) -> RelateResult<'tcx, ImplSubject<'tcx>> {
|
||||
a: ty::ImplSubject<'tcx>,
|
||||
b: ty::ImplSubject<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::ImplSubject<'tcx>> {
|
||||
match (a, b) {
|
||||
(ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
|
||||
(ty::ImplSubject::Trait(trait_ref_a), ty::ImplSubject::Trait(trait_ref_b)) => {
|
||||
let trait_ref = ty::TraitRef::relate(relation, trait_ref_a, trait_ref_b)?;
|
||||
Ok(ImplSubject::Trait(trait_ref))
|
||||
Ok(ty::ImplSubject::Trait(trait_ref))
|
||||
}
|
||||
(ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
|
||||
(ty::ImplSubject::Inherent(ty_a), ty::ImplSubject::Inherent(ty_b)) => {
|
||||
let ty = Ty::relate(relation, ty_a, ty_b)?;
|
||||
Ok(ImplSubject::Inherent(ty))
|
||||
Ok(ty::ImplSubject::Inherent(ty))
|
||||
}
|
||||
(ImplSubject::Trait(_), ImplSubject::Inherent(_))
|
||||
| (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
|
||||
(ty::ImplSubject::Trait(_), ty::ImplSubject::Inherent(_))
|
||||
| (ty::ImplSubject::Inherent(_), ty::ImplSubject::Trait(_)) => {
|
||||
bug!("can not relate TraitRef and Ty");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
#[inline]
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
@ -386,9 +57,9 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for Pattern<'tcx> {
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
|
||||
#[inline]
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: Self,
|
||||
b: Self,
|
||||
@ -416,276 +87,8 @@ impl<'tcx> Relate<'tcx> for Pattern<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Relates `a` and `b` structurally, calling the relation for all nested values.
|
||||
/// Any semantic equality, e.g. of projections, and inference variables have to be
|
||||
/// handled by the caller.
|
||||
#[instrument(level = "trace", skip(relation), ret)]
|
||||
pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let tcx = relation.tcx();
|
||||
match (a.kind(), b.kind()) {
|
||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
||||
// The caller should handle these cases!
|
||||
bug!("var types encountered in structurally_relate_tys")
|
||||
}
|
||||
|
||||
(ty::Bound(..), _) | (_, ty::Bound(..)) => {
|
||||
bug!("bound types encountered in structurally_relate_tys")
|
||||
}
|
||||
|
||||
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
|
||||
|
||||
(&ty::Never, _)
|
||||
| (&ty::Char, _)
|
||||
| (&ty::Bool, _)
|
||||
| (&ty::Int(_), _)
|
||||
| (&ty::Uint(_), _)
|
||||
| (&ty::Float(_), _)
|
||||
| (&ty::Str, _)
|
||||
if a == b =>
|
||||
{
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
(ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => {
|
||||
debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
(ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
|
||||
|
||||
(&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def => {
|
||||
let args = relation.relate_item_args(a_def.did(), a_args, b_args)?;
|
||||
Ok(Ty::new_adt(tcx, a_def, args))
|
||||
}
|
||||
|
||||
(&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
|
||||
|
||||
(&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr))
|
||||
if a_repr == b_repr =>
|
||||
{
|
||||
Ok(Ty::new_dynamic(
|
||||
tcx,
|
||||
relation.relate(a_obj, b_obj)?,
|
||||
relation.relate(a_region, b_region)?,
|
||||
a_repr,
|
||||
))
|
||||
}
|
||||
|
||||
(&ty::Coroutine(a_id, a_args), &ty::Coroutine(b_id, b_args)) if a_id == b_id => {
|
||||
// All Coroutine types with the same id represent
|
||||
// the (anonymous) type of the same coroutine expression. So
|
||||
// all of their regions should be equated.
|
||||
let args = relate_args_invariantly(relation, a_args, b_args)?;
|
||||
Ok(Ty::new_coroutine(tcx, a_id, args))
|
||||
}
|
||||
|
||||
(&ty::CoroutineWitness(a_id, a_args), &ty::CoroutineWitness(b_id, b_args))
|
||||
if a_id == b_id =>
|
||||
{
|
||||
// All CoroutineWitness types with the same id represent
|
||||
// the (anonymous) type of the same coroutine expression. So
|
||||
// all of their regions should be equated.
|
||||
let args = relate_args_invariantly(relation, a_args, b_args)?;
|
||||
Ok(Ty::new_coroutine_witness(tcx, a_id, args))
|
||||
}
|
||||
|
||||
(&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => {
|
||||
// All Closure types with the same id represent
|
||||
// the (anonymous) type of the same closure expression. So
|
||||
// all of their regions should be equated.
|
||||
let args = relate_args_invariantly(relation, a_args, b_args)?;
|
||||
Ok(Ty::new_closure(tcx, a_id, args))
|
||||
}
|
||||
|
||||
(&ty::CoroutineClosure(a_id, a_args), &ty::CoroutineClosure(b_id, b_args))
|
||||
if a_id == b_id =>
|
||||
{
|
||||
let args = relate_args_invariantly(relation, a_args, b_args)?;
|
||||
Ok(Ty::new_coroutine_closure(tcx, a_id, args))
|
||||
}
|
||||
|
||||
(&ty::RawPtr(a_ty, a_mutbl), &ty::RawPtr(b_ty, b_mutbl)) => {
|
||||
if a_mutbl != b_mutbl {
|
||||
return Err(TypeError::Mutability);
|
||||
}
|
||||
|
||||
let (variance, info) = match a_mutbl {
|
||||
hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
|
||||
hir::Mutability::Mut => {
|
||||
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
|
||||
}
|
||||
};
|
||||
|
||||
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
|
||||
|
||||
Ok(Ty::new_ptr(tcx, ty, a_mutbl))
|
||||
}
|
||||
|
||||
(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
|
||||
if a_mutbl != b_mutbl {
|
||||
return Err(TypeError::Mutability);
|
||||
}
|
||||
|
||||
let (variance, info) = match a_mutbl {
|
||||
hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
|
||||
hir::Mutability::Mut => {
|
||||
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
|
||||
}
|
||||
};
|
||||
|
||||
let r = relation.relate(a_r, b_r)?;
|
||||
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
|
||||
|
||||
Ok(Ty::new_ref(tcx, r, ty, a_mutbl))
|
||||
}
|
||||
|
||||
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
|
||||
let t = relation.relate(a_t, b_t)?;
|
||||
match relation.relate(sz_a, sz_b) {
|
||||
Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
|
||||
Err(err) => {
|
||||
// Check whether the lengths are both concrete/known values,
|
||||
// but are unequal, for better diagnostics.
|
||||
let sz_a = sz_a.try_to_target_usize(tcx);
|
||||
let sz_b = sz_b.try_to_target_usize(tcx);
|
||||
|
||||
match (sz_a, sz_b) {
|
||||
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => {
|
||||
Err(TypeError::FixedArraySize(expected_found(sz_a_val, sz_b_val)))
|
||||
}
|
||||
_ => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::Slice(a_t), &ty::Slice(b_t)) => {
|
||||
let t = relation.relate(a_t, b_t)?;
|
||||
Ok(Ty::new_slice(tcx, t))
|
||||
}
|
||||
|
||||
(&ty::Tuple(as_), &ty::Tuple(bs)) => {
|
||||
if as_.len() == bs.len() {
|
||||
Ok(Ty::new_tup_from_iter(
|
||||
tcx,
|
||||
iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)),
|
||||
)?)
|
||||
} else if !(as_.is_empty() || bs.is_empty()) {
|
||||
Err(TypeError::TupleSize(expected_found(as_.len(), bs.len())))
|
||||
} else {
|
||||
Err(TypeError::Sorts(expected_found(a, b)))
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::FnDef(a_def_id, a_args), &ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
|
||||
let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
|
||||
Ok(Ty::new_fn_def(tcx, a_def_id, args))
|
||||
}
|
||||
|
||||
(&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
|
||||
let fty = relation.relate(a_fty, b_fty)?;
|
||||
Ok(Ty::new_fn_ptr(tcx, fty))
|
||||
}
|
||||
|
||||
// Alias tend to mostly already be handled downstream due to normalization.
|
||||
(&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
|
||||
let alias_ty = relation.relate(a_data, b_data)?;
|
||||
assert_eq!(a_kind, b_kind);
|
||||
Ok(Ty::new_alias(tcx, a_kind, alias_ty))
|
||||
}
|
||||
|
||||
(&ty::Pat(a_ty, a_pat), &ty::Pat(b_ty, b_pat)) => {
|
||||
let ty = relation.relate(a_ty, b_ty)?;
|
||||
let pat = relation.relate(a_pat, b_pat)?;
|
||||
Ok(Ty::new_pat(tcx, ty, pat))
|
||||
}
|
||||
|
||||
_ => Err(TypeError::Sorts(expected_found(a, b))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Relates `a` and `b` structurally, calling the relation for all nested values.
|
||||
/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
|
||||
/// to be handled by the caller.
|
||||
///
|
||||
/// FIXME: This is not totally structual, which probably should be fixed.
|
||||
/// See the HACKs below.
|
||||
pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
mut a: ty::Const<'tcx>,
|
||||
mut b: ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
|
||||
let tcx = relation.tcx();
|
||||
|
||||
if tcx.features().generic_const_exprs {
|
||||
a = tcx.expand_abstract_consts(a);
|
||||
b = tcx.expand_abstract_consts(b);
|
||||
}
|
||||
|
||||
debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
|
||||
|
||||
// Currently, the values that can be unified are primitive types,
|
||||
// and those that derive both `PartialEq` and `Eq`, corresponding
|
||||
// to structural-match types.
|
||||
let is_match = match (a.kind(), b.kind()) {
|
||||
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
|
||||
// The caller should handle these cases!
|
||||
bug!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
|
||||
}
|
||||
|
||||
(ty::ConstKind::Error(_), _) => return Ok(a),
|
||||
(_, ty::ConstKind::Error(_)) => return Ok(b),
|
||||
|
||||
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => {
|
||||
debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
|
||||
true
|
||||
}
|
||||
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
||||
(ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val,
|
||||
|
||||
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
|
||||
// and is the better alternative to waiting until `generic_const_exprs` can
|
||||
// be stabilized.
|
||||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
|
||||
if cfg!(debug_assertions) {
|
||||
let a_ty = tcx.type_of(au.def).instantiate(tcx, au.args);
|
||||
let b_ty = tcx.type_of(bu.def).instantiate(tcx, bu.args);
|
||||
assert_eq!(a_ty, b_ty);
|
||||
}
|
||||
|
||||
let args = relation.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
au.args,
|
||||
bu.args,
|
||||
)?;
|
||||
return Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args }));
|
||||
}
|
||||
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
|
||||
match (ae.kind, be.kind) {
|
||||
(ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop))
|
||||
if a_binop == b_binop => {}
|
||||
(ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {}
|
||||
(ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {}
|
||||
(ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {}
|
||||
_ => return Err(TypeError::ConstMismatch(expected_found(a, b))),
|
||||
}
|
||||
|
||||
let args = relation.relate(ae.args(), be.args())?;
|
||||
return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args)));
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(a, b))) }
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: Self,
|
||||
b: Self,
|
||||
@ -703,44 +106,65 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
|
||||
b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
||||
b_v.dedup();
|
||||
if a_v.len() != b_v.len() {
|
||||
return Err(TypeError::ExistentialMismatch(expected_found(a, b)));
|
||||
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b)));
|
||||
}
|
||||
|
||||
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
|
||||
match (ep_a.skip_binder(), ep_b.skip_binder()) {
|
||||
(ExistentialPredicate::Trait(a), ExistentialPredicate::Trait(b)) => Ok(ep_a
|
||||
.rebind(ExistentialPredicate::Trait(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
))),
|
||||
(ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
|
||||
Ok(ep_a.rebind(ExistentialPredicate::Projection(
|
||||
(ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
|
||||
Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
)))
|
||||
}
|
||||
(ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b))
|
||||
if a == b =>
|
||||
{
|
||||
Ok(ep_a.rebind(ExistentialPredicate::AutoTrait(a)))
|
||||
}
|
||||
_ => Err(TypeError::ExistentialMismatch(expected_found(a, b))),
|
||||
(
|
||||
ty::ExistentialPredicate::Projection(a),
|
||||
ty::ExistentialPredicate::Projection(b),
|
||||
) => Ok(ep_a.rebind(ty::ExistentialPredicate::Projection(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
))),
|
||||
(
|
||||
ty::ExistentialPredicate::AutoTrait(a),
|
||||
ty::ExistentialPredicate::AutoTrait(b),
|
||||
) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
|
||||
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b))),
|
||||
}
|
||||
});
|
||||
tcx.mk_poly_existential_predicates_from_iter(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for GenericArgsRef<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for hir::Safety {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
_relation: &mut R,
|
||||
a: hir::Safety,
|
||||
b: hir::Safety,
|
||||
) -> RelateResult<'tcx, hir::Safety> {
|
||||
if a != b { Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a, b))) } else { Ok(a) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for abi::Abi {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
_relation: &mut R,
|
||||
a: abi::Abi,
|
||||
b: abi::Abi,
|
||||
) -> RelateResult<'tcx, abi::Abi> {
|
||||
if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(ExpectedFound::new(true, a, b))) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: GenericArgsRef<'tcx>,
|
||||
b: GenericArgsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
|
||||
a: ty::GenericArgsRef<'tcx>,
|
||||
b: ty::GenericArgsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
|
||||
relate_args_invariantly(relation, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Region<'tcx> {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
@ -749,8 +173,8 @@ impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::Const<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: ty::Const<'tcx>,
|
||||
b: ty::Const<'tcx>,
|
||||
@ -759,85 +183,70 @@ impl<'tcx> Relate<'tcx> for ty::Const<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Expr<'tcx> {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: ty::Binder<'tcx, T>,
|
||||
b: ty::Binder<'tcx, T>,
|
||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
|
||||
relation.binders(a, b)
|
||||
ae: ty::Expr<'tcx>,
|
||||
be: ty::Expr<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Expr<'tcx>> {
|
||||
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
|
||||
// exprs? Should we care about that?
|
||||
// FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
|
||||
// ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
|
||||
// of as being generic over the argument types, however this is implicit so these types don't get
|
||||
// related when we relate the args of the item this const arg is for.
|
||||
match (ae.kind, be.kind) {
|
||||
(ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop)) if a_binop == b_binop => {}
|
||||
(ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {}
|
||||
(ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {}
|
||||
(ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {}
|
||||
_ => return Err(TypeError::Mismatch),
|
||||
}
|
||||
|
||||
let args = relation.relate(ae.args(), be.args())?;
|
||||
Ok(ty::Expr::new(ae.kind, args))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArg<'tcx> {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: GenericArg<'tcx>,
|
||||
b: GenericArg<'tcx>,
|
||||
) -> RelateResult<'tcx, GenericArg<'tcx>> {
|
||||
a: ty::GenericArg<'tcx>,
|
||||
b: ty::GenericArg<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::GenericArg<'tcx>> {
|
||||
match (a.unpack(), b.unpack()) {
|
||||
(GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => {
|
||||
(ty::GenericArgKind::Lifetime(a_lt), ty::GenericArgKind::Lifetime(b_lt)) => {
|
||||
Ok(relation.relate(a_lt, b_lt)?.into())
|
||||
}
|
||||
(GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => {
|
||||
(ty::GenericArgKind::Type(a_ty), ty::GenericArgKind::Type(b_ty)) => {
|
||||
Ok(relation.relate(a_ty, b_ty)?.into())
|
||||
}
|
||||
(GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => {
|
||||
(ty::GenericArgKind::Const(a_ct), ty::GenericArgKind::Const(b_ct)) => {
|
||||
Ok(relation.relate(a_ct, b_ct)?.into())
|
||||
}
|
||||
(GenericArgKind::Lifetime(unpacked), x) => {
|
||||
(ty::GenericArgKind::Lifetime(unpacked), x) => {
|
||||
bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
|
||||
}
|
||||
(GenericArgKind::Type(unpacked), x) => {
|
||||
(ty::GenericArgKind::Type(unpacked), x) => {
|
||||
bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
|
||||
}
|
||||
(GenericArgKind::Const(unpacked), x) => {
|
||||
(ty::GenericArgKind::Const(unpacked), x) => {
|
||||
bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::PredicatePolarity {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
_relation: &mut R,
|
||||
a: ty::PredicatePolarity,
|
||||
b: ty::PredicatePolarity,
|
||||
) -> RelateResult<'tcx, ty::PredicatePolarity> {
|
||||
if a != b { Err(TypeError::PolarityMismatch(expected_found(a, b))) } else { Ok(a) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::TraitPredicate<'tcx>,
|
||||
b: ty::TraitPredicate<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> {
|
||||
Ok(ty::TraitPredicate {
|
||||
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
|
||||
polarity: relation.relate(a.polarity, b.polarity)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for Term<'tcx> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Term<'tcx> {
|
||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||
relation: &mut R,
|
||||
a: Self,
|
||||
b: Self,
|
||||
) -> RelateResult<'tcx, Self> {
|
||||
Ok(match (a.unpack(), b.unpack()) {
|
||||
(TermKind::Ty(a), TermKind::Ty(b)) => relation.relate(a, b)?.into(),
|
||||
(TermKind::Const(a), TermKind::Const(b)) => relation.relate(a, b)?.into(),
|
||||
(ty::TermKind::Ty(a), ty::TermKind::Ty(b)) => relation.relate(a, b)?.into(),
|
||||
(ty::TermKind::Const(a), ty::TermKind::Const(b)) => relation.relate(a, b)?.into(),
|
||||
_ => return Err(TypeError::Mismatch),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Error handling
|
||||
|
||||
pub fn expected_found<T>(a: T, b: T) -> ExpectedFound<T> {
|
||||
ExpectedFound::new(true, a, b)
|
||||
}
|
||||
|
@ -296,7 +296,6 @@ TrivialTypeTraversalImpls! {
|
||||
::rustc_target::abi::FieldIdx,
|
||||
::rustc_target::abi::VariantIdx,
|
||||
crate::middle::region::Scope,
|
||||
crate::ty::FloatTy,
|
||||
::rustc_ast::InlineAsmOptions,
|
||||
::rustc_ast::InlineAsmTemplatePiece,
|
||||
::rustc_ast::NodeId,
|
||||
@ -316,7 +315,7 @@ TrivialTypeTraversalImpls! {
|
||||
crate::traits::Reveal,
|
||||
crate::ty::adjustment::AutoBorrowMutability,
|
||||
crate::ty::AdtKind,
|
||||
crate::ty::BoundConstness,
|
||||
crate::ty::BoundRegion,
|
||||
// Including `BoundRegionKind` is a *bit* dubious, but direct
|
||||
// references to bound region appear in `ty::Error`, and aren't
|
||||
// really meant to be folded. In general, we can only fold a fully
|
||||
@ -324,16 +323,11 @@ TrivialTypeTraversalImpls! {
|
||||
crate::ty::BoundRegionKind,
|
||||
crate::ty::AssocItem,
|
||||
crate::ty::AssocKind,
|
||||
crate::ty::AliasTyKind,
|
||||
crate::ty::Placeholder<crate::ty::BoundRegion>,
|
||||
crate::ty::Placeholder<crate::ty::BoundTy>,
|
||||
crate::ty::Placeholder<ty::BoundVar>,
|
||||
crate::ty::LateParamRegion,
|
||||
crate::ty::InferTy,
|
||||
crate::ty::IntVarValue,
|
||||
crate::ty::adjustment::PointerCoercion,
|
||||
crate::ty::RegionVid,
|
||||
crate::ty::Variance,
|
||||
::rustc_span::Span,
|
||||
::rustc_span::symbol::Ident,
|
||||
::rustc_errors::ErrorGuaranteed,
|
||||
|
@ -810,6 +810,31 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
Ty::new_alias(interner, kind, alias_ty)
|
||||
}
|
||||
|
||||
fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
|
||||
Ty::new_error(interner, guar)
|
||||
}
|
||||
|
||||
fn new_adt(
|
||||
interner: TyCtxt<'tcx>,
|
||||
adt_def: ty::AdtDef<'tcx>,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> Self {
|
||||
Ty::new_adt(interner, adt_def, args)
|
||||
}
|
||||
|
||||
fn new_foreign(interner: TyCtxt<'tcx>, def_id: DefId) -> Self {
|
||||
Ty::new_foreign(interner, def_id)
|
||||
}
|
||||
|
||||
fn new_dynamic(
|
||||
interner: TyCtxt<'tcx>,
|
||||
preds: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
region: ty::Region<'tcx>,
|
||||
kind: ty::DynKind,
|
||||
) -> Self {
|
||||
Ty::new_dynamic(interner, preds, region, kind)
|
||||
}
|
||||
|
||||
fn new_coroutine(
|
||||
interner: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
@ -818,6 +843,51 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
Ty::new_coroutine(interner, def_id, args)
|
||||
}
|
||||
|
||||
fn new_coroutine_closure(
|
||||
interner: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> Self {
|
||||
Ty::new_coroutine_closure(interner, def_id, args)
|
||||
}
|
||||
|
||||
fn new_closure(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
|
||||
Ty::new_closure(interner, def_id, args)
|
||||
}
|
||||
|
||||
fn new_coroutine_witness(
|
||||
interner: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> Self {
|
||||
Ty::new_coroutine_witness(interner, def_id, args)
|
||||
}
|
||||
|
||||
fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
|
||||
Ty::new_ptr(interner, ty, mutbl)
|
||||
}
|
||||
|
||||
fn new_ref(
|
||||
interner: TyCtxt<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
ty: Self,
|
||||
mutbl: hir::Mutability,
|
||||
) -> Self {
|
||||
Ty::new_ref(interner, region, ty, mutbl)
|
||||
}
|
||||
|
||||
fn new_array_with_const_len(interner: TyCtxt<'tcx>, ty: Self, len: ty::Const<'tcx>) -> Self {
|
||||
Ty::new_array_with_const_len(interner, ty, len)
|
||||
}
|
||||
|
||||
fn new_slice(interner: TyCtxt<'tcx>, ty: Self) -> Self {
|
||||
Ty::new_slice(interner, ty)
|
||||
}
|
||||
|
||||
fn new_tup(interner: TyCtxt<'tcx>, tys: &[Ty<'tcx>]) -> Self {
|
||||
Ty::new_tup(interner, tys)
|
||||
}
|
||||
|
||||
fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
|
||||
where
|
||||
It: Iterator<Item = T>,
|
||||
@ -844,6 +914,18 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
) -> Self {
|
||||
Ty::from_coroutine_closure_kind(interner, kind)
|
||||
}
|
||||
|
||||
fn new_fn_def(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
|
||||
Ty::new_fn_def(interner, def_id, args)
|
||||
}
|
||||
|
||||
fn new_fn_ptr(interner: TyCtxt<'tcx>, sig: ty::Binder<'tcx, ty::FnSig<'tcx>>) -> Self {
|
||||
Ty::new_fn_ptr(interner, sig)
|
||||
}
|
||||
|
||||
fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self {
|
||||
Ty::new_pat(interner, ty, pat)
|
||||
}
|
||||
}
|
||||
|
||||
/// Type utilities
|
||||
@ -1812,43 +1894,6 @@ impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx
|
||||
}
|
||||
}
|
||||
|
||||
/// Extra information about why we ended up with a particular variance.
|
||||
/// This is only used to add more information to error messages, and
|
||||
/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
|
||||
/// may lead to confusing notes in error messages, it will never cause
|
||||
/// a miscompilation or unsoundness.
|
||||
///
|
||||
/// When in doubt, use `VarianceDiagInfo::default()`
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub enum VarianceDiagInfo<'tcx> {
|
||||
/// No additional information - this is the default.
|
||||
/// We will not add any additional information to error messages.
|
||||
#[default]
|
||||
None,
|
||||
/// We switched our variance because a generic argument occurs inside
|
||||
/// the invariant generic argument of another type.
|
||||
Invariant {
|
||||
/// The generic type containing the generic parameter
|
||||
/// that changes the variance (e.g. `*mut T`, `MyStruct<T>`)
|
||||
ty: Ty<'tcx>,
|
||||
/// The index of the generic parameter being used
|
||||
/// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`)
|
||||
param_index: u32,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'tcx> VarianceDiagInfo<'tcx> {
|
||||
/// Mirrors `Variance::xform` - used to 'combine' the existing
|
||||
/// and new `VarianceDiagInfo`s when our variance changes.
|
||||
pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> {
|
||||
// For now, just use the first `VarianceDiagInfo::Invariant` that we see
|
||||
match self {
|
||||
VarianceDiagInfo::None => other,
|
||||
VarianceDiagInfo::Invariant { .. } => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some types are used a lot. Make sure they don't unintentionally get bigger.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod size_asserts {
|
||||
|
@ -217,10 +217,6 @@ pub struct TypeckResults<'tcx> {
|
||||
|
||||
/// Container types and field indices of `offset_of!` expressions
|
||||
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
|
||||
|
||||
/// Maps from `HirId`s of const blocks (the `ExprKind::ConstBlock`, not the inner expression's)
|
||||
/// to the `DefId` of the corresponding inline const.
|
||||
pub inline_consts: FxIndexMap<ItemLocalId, LocalDefId>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeckResults<'tcx> {
|
||||
@ -253,7 +249,6 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
treat_byte_string_as_slice: Default::default(),
|
||||
closure_size_eval: Default::default(),
|
||||
offset_of_data: Default::default(),
|
||||
inline_consts: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,8 +568,11 @@ fn construct_const<'a, 'tcx>(
|
||||
..
|
||||
}) => (*span, ty.span),
|
||||
Node::AnonConst(ct) => (ct.span, ct.span),
|
||||
Node::Expr(&hir::Expr { span, kind: hir::ExprKind::ConstBlock(_), .. }) => (span, span),
|
||||
node => span_bug!(tcx.def_span(def), "can't build MIR for {def:?}: {node:#?}"),
|
||||
Node::ConstBlock(_) => {
|
||||
let span = tcx.def_span(def);
|
||||
(span, span)
|
||||
}
|
||||
_ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
|
||||
};
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
|
@ -671,9 +671,9 @@ impl<'tcx> Cx<'tcx> {
|
||||
ExprKind::OffsetOf { container, fields }
|
||||
}
|
||||
|
||||
hir::ExprKind::ConstBlock(body) => {
|
||||
let ty = self.typeck_results().node_type(body.hir_id);
|
||||
let did = self.typeck_results().inline_consts[&expr.hir_id.local_id].into();
|
||||
hir::ExprKind::ConstBlock(ref anon_const) => {
|
||||
let ty = self.typeck_results().node_type(anon_const.hir_id);
|
||||
let did = anon_const.def_id.to_def_id();
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(did);
|
||||
let parent_args =
|
||||
tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id));
|
||||
|
@ -165,7 +165,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
&'a mut self,
|
||||
owner_id: HirId,
|
||||
fn_decl: &'tcx hir::FnDecl<'tcx>,
|
||||
body: &hir::Body<'tcx>,
|
||||
body: &'tcx hir::Body<'tcx>,
|
||||
) -> impl Iterator<Item = Param<'tcx>> + 'a {
|
||||
let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id];
|
||||
|
||||
|
@ -637,13 +637,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
/// Converts inline const patterns.
|
||||
fn lower_inline_const(
|
||||
&mut self,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
block: &'tcx hir::ConstBlock,
|
||||
id: hir::HirId,
|
||||
span: Span,
|
||||
) -> PatKind<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let def_id = self.typeck_results.inline_consts[&id.local_id];
|
||||
let ty = tcx.typeck(def_id).node_type(expr.hir_id);
|
||||
let def_id = block.def_id;
|
||||
let body_id = block.body;
|
||||
let expr = &tcx.hir().body(body_id).value;
|
||||
let ty = tcx.typeck(def_id).node_type(block.hir_id);
|
||||
|
||||
// Special case inline consts that are just literals. This is solely
|
||||
// a performance optimization, as we could also just go through the regular
|
||||
|
@ -211,7 +211,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
|
||||
}
|
||||
|
||||
fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
tcx.hir().maybe_body_owned_by(def_id).is_some()
|
||||
tcx.mir_keys(()).contains(&def_id)
|
||||
}
|
||||
|
||||
/// Finds the full set of `DefId`s within the current crate that have
|
||||
@ -222,16 +222,6 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
|
||||
// All body-owners have MIR associated with them.
|
||||
set.extend(tcx.hir().body_owners());
|
||||
|
||||
// Inline consts' bodies are created in
|
||||
// typeck instead of during ast lowering, like all other bodies so far.
|
||||
for def_id in tcx.hir().body_owners() {
|
||||
// Incremental performance optimization: only load typeck results for things that actually have inline consts
|
||||
if tcx.hir_owner_nodes(tcx.hir().body_owned_by(def_id).id().hir_id.owner).has_inline_consts
|
||||
{
|
||||
set.extend(tcx.typeck(def_id).inline_consts.values())
|
||||
}
|
||||
}
|
||||
|
||||
// Additionally, tuple struct/variant constructors have MIR, but
|
||||
// they don't have a BodyId, so we need to build them separately.
|
||||
struct GatherCtors<'a> {
|
||||
|
@ -207,8 +207,8 @@
|
||||
|
||||
mod move_check;
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::{par_for_each_in, LRef, MTLock};
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
@ -251,10 +251,10 @@ pub enum MonoItemCollectionStrategy {
|
||||
|
||||
pub struct UsageMap<'tcx> {
|
||||
// Maps every mono item to the mono items used by it.
|
||||
used_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
|
||||
used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
|
||||
|
||||
// Maps every mono item to the mono items that use it.
|
||||
user_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
|
||||
user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
|
||||
}
|
||||
|
||||
type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;
|
||||
@ -262,10 +262,10 @@ type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;
|
||||
/// The state that is shared across the concurrent threads that are doing collection.
|
||||
struct SharedState<'tcx> {
|
||||
/// Items that have been or are currently being recursively collected.
|
||||
visited: MTLock<FxHashSet<MonoItem<'tcx>>>,
|
||||
visited: MTLock<UnordSet<MonoItem<'tcx>>>,
|
||||
/// Items that have been or are currently being recursively treated as "mentioned", i.e., their
|
||||
/// consts are evaluated but nothing is added to the collection.
|
||||
mentioned: MTLock<FxHashSet<MonoItem<'tcx>>>,
|
||||
mentioned: MTLock<UnordSet<MonoItem<'tcx>>>,
|
||||
/// Which items are being used where, for better errors.
|
||||
usage_map: MTLock<UsageMap<'tcx>>,
|
||||
}
|
||||
@ -290,7 +290,7 @@ enum CollectionMode {
|
||||
|
||||
impl<'tcx> UsageMap<'tcx> {
|
||||
fn new() -> UsageMap<'tcx> {
|
||||
UsageMap { used_map: FxHashMap::default(), user_map: FxHashMap::default() }
|
||||
UsageMap { used_map: Default::default(), user_map: Default::default() }
|
||||
}
|
||||
|
||||
fn record_used<'a>(
|
||||
@ -668,7 +668,7 @@ struct MirUsedCollector<'a, 'tcx> {
|
||||
used_items: &'a mut MonoItems<'tcx>,
|
||||
/// See the comment in `collect_items_of_instance` for the purpose of this set.
|
||||
/// Note that this contains *not-monomorphized* items!
|
||||
used_mentioned_items: &'a mut FxHashSet<MentionedItem<'tcx>>,
|
||||
used_mentioned_items: &'a mut UnordSet<MentionedItem<'tcx>>,
|
||||
instance: Instance<'tcx>,
|
||||
visiting_call_terminator: bool,
|
||||
move_check: move_check::MoveCheckState,
|
||||
@ -1272,7 +1272,7 @@ fn collect_items_of_instance<'tcx>(
|
||||
// mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
|
||||
// added to `used_items` in a hash set, which can efficiently query in the
|
||||
// `body.mentioned_items` loop below without even having to monomorphize the item.
|
||||
let mut used_mentioned_items = FxHashSet::<MentionedItem<'tcx>>::default();
|
||||
let mut used_mentioned_items = Default::default();
|
||||
let mut collector = MirUsedCollector {
|
||||
tcx,
|
||||
body,
|
||||
@ -1628,10 +1628,10 @@ fn create_mono_items_for_default_impls<'tcx>(
|
||||
//=-----------------------------------------------------------------------------
|
||||
|
||||
#[instrument(skip(tcx, strategy), level = "debug")]
|
||||
pub fn collect_crate_mono_items(
|
||||
tcx: TyCtxt<'_>,
|
||||
pub(crate) fn collect_crate_mono_items<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
strategy: MonoItemCollectionStrategy,
|
||||
) -> (FxHashSet<MonoItem<'_>>, UsageMap<'_>) {
|
||||
) -> (Vec<MonoItem<'tcx>>, UsageMap<'tcx>) {
|
||||
let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");
|
||||
|
||||
let roots = tcx
|
||||
@ -1641,8 +1641,8 @@ pub fn collect_crate_mono_items(
|
||||
debug!("building mono item graph, beginning at roots");
|
||||
|
||||
let mut state = SharedState {
|
||||
visited: MTLock::new(FxHashSet::default()),
|
||||
mentioned: MTLock::new(FxHashSet::default()),
|
||||
visited: MTLock::new(UnordSet::default()),
|
||||
mentioned: MTLock::new(UnordSet::default()),
|
||||
usage_map: MTLock::new(UsageMap::new()),
|
||||
};
|
||||
let recursion_limit = tcx.recursion_limit();
|
||||
@ -1665,5 +1665,11 @@ pub fn collect_crate_mono_items(
|
||||
});
|
||||
}
|
||||
|
||||
(state.visited.into_inner(), state.usage_map.into_inner())
|
||||
// The set of MonoItems was created in an inherently indeterministic order because
|
||||
// of parallelism. We sort it here to ensure that the output is deterministic.
|
||||
let mono_items = tcx.with_stable_hashing_context(move |ref hcx| {
|
||||
state.visited.into_inner().into_sorted(hcx, true)
|
||||
});
|
||||
|
||||
(mono_items, state.usage_map.into_inner())
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#![feature(array_windows)]
|
||||
#![feature(is_sorted)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_middle::bug;
|
||||
|
@ -98,8 +98,9 @@ use std::fs::{self, File};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::DefPathDataName;
|
||||
@ -131,7 +132,7 @@ struct PlacedMonoItems<'tcx> {
|
||||
/// The codegen units, sorted by name to make things deterministic.
|
||||
codegen_units: Vec<CodegenUnit<'tcx>>,
|
||||
|
||||
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
|
||||
internalization_candidates: UnordSet<MonoItem<'tcx>>,
|
||||
}
|
||||
|
||||
// The output CGUs are sorted by name.
|
||||
@ -197,9 +198,9 @@ fn place_mono_items<'tcx, I>(cx: &PartitioningCx<'_, 'tcx>, mono_items: I) -> Pl
|
||||
where
|
||||
I: Iterator<Item = MonoItem<'tcx>>,
|
||||
{
|
||||
let mut codegen_units = FxHashMap::default();
|
||||
let mut codegen_units = UnordMap::default();
|
||||
let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
|
||||
let mut internalization_candidates = FxHashSet::default();
|
||||
let mut internalization_candidates = UnordSet::default();
|
||||
|
||||
// Determine if monomorphizations instantiated in this crate will be made
|
||||
// available to downstream crates. This depends on whether we are in
|
||||
@ -209,7 +210,7 @@ where
|
||||
cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
|
||||
|
||||
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
|
||||
let cgu_name_cache = &mut FxHashMap::default();
|
||||
let cgu_name_cache = &mut UnordMap::default();
|
||||
|
||||
for mono_item in mono_items {
|
||||
// Handle only root (GloballyShared) items directly here. Inlined (LocalCopy) items
|
||||
@ -260,7 +261,7 @@ where
|
||||
// going via another root item. This includes drop-glue, functions from
|
||||
// external crates, and local functions the definition of which is
|
||||
// marked with `#[inline]`.
|
||||
let mut reachable_inlined_items = FxHashSet::default();
|
||||
let mut reachable_inlined_items = FxIndexSet::default();
|
||||
get_reachable_inlined_items(cx.tcx, mono_item, cx.usage_map, &mut reachable_inlined_items);
|
||||
|
||||
// Add those inlined items. It's possible an inlined item is reachable
|
||||
@ -284,8 +285,9 @@ where
|
||||
codegen_units.insert(cgu_name, CodegenUnit::new(cgu_name));
|
||||
}
|
||||
|
||||
let mut codegen_units: Vec<_> = codegen_units.into_values().collect();
|
||||
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
|
||||
let mut codegen_units: Vec<_> = cx.tcx.with_stable_hashing_context(|ref hcx| {
|
||||
codegen_units.into_items().map(|(_, cgu)| cgu).collect_sorted(hcx, true)
|
||||
});
|
||||
|
||||
for cgu in codegen_units.iter_mut() {
|
||||
cgu.compute_size_estimate();
|
||||
@ -297,7 +299,7 @@ where
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: MonoItem<'tcx>,
|
||||
usage_map: &UsageMap<'tcx>,
|
||||
visited: &mut FxHashSet<MonoItem<'tcx>>,
|
||||
visited: &mut FxIndexSet<MonoItem<'tcx>>,
|
||||
) {
|
||||
usage_map.for_each_inlined_used_item(tcx, item, |inlined_item| {
|
||||
let is_new = visited.insert(inlined_item);
|
||||
@ -320,7 +322,7 @@ fn merge_codegen_units<'tcx>(
|
||||
assert!(codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()));
|
||||
|
||||
// This map keeps track of what got merged into what.
|
||||
let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
|
||||
let mut cgu_contents: UnordMap<Symbol, Vec<Symbol>> =
|
||||
codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
|
||||
|
||||
// If N is the maximum number of CGUs, and the CGUs are sorted from largest
|
||||
@ -422,22 +424,24 @@ fn merge_codegen_units<'tcx>(
|
||||
// For CGUs that contain the code of multiple modules because of the
|
||||
// merging done above, we use a concatenation of the names of all
|
||||
// contained CGUs.
|
||||
let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
|
||||
.into_iter()
|
||||
// This `filter` makes sure we only update the name of CGUs that
|
||||
// were actually modified by merging.
|
||||
.filter(|(_, cgu_contents)| cgu_contents.len() > 1)
|
||||
.map(|(current_cgu_name, cgu_contents)| {
|
||||
let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect();
|
||||
let new_cgu_names = UnordMap::from(
|
||||
cgu_contents
|
||||
.items()
|
||||
// This `filter` makes sure we only update the name of CGUs that
|
||||
// were actually modified by merging.
|
||||
.filter(|(_, cgu_contents)| cgu_contents.len() > 1)
|
||||
.map(|(current_cgu_name, cgu_contents)| {
|
||||
let mut cgu_contents: Vec<&str> =
|
||||
cgu_contents.iter().map(|s| s.as_str()).collect();
|
||||
|
||||
// Sort the names, so things are deterministic and easy to
|
||||
// predict. We are sorting primitive `&str`s here so we can
|
||||
// use unstable sort.
|
||||
cgu_contents.sort_unstable();
|
||||
// Sort the names, so things are deterministic and easy to
|
||||
// predict. We are sorting primitive `&str`s here so we can
|
||||
// use unstable sort.
|
||||
cgu_contents.sort_unstable();
|
||||
|
||||
(current_cgu_name, cgu_contents.join("--"))
|
||||
})
|
||||
.collect();
|
||||
(*current_cgu_name, cgu_contents.join("--"))
|
||||
}),
|
||||
);
|
||||
|
||||
for cgu in codegen_units.iter_mut() {
|
||||
if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
|
||||
@ -511,7 +515,7 @@ fn compute_inlined_overlap<'tcx>(cgu1: &CodegenUnit<'tcx>, cgu2: &CodegenUnit<'t
|
||||
fn internalize_symbols<'tcx>(
|
||||
cx: &PartitioningCx<'_, 'tcx>,
|
||||
codegen_units: &mut [CodegenUnit<'tcx>],
|
||||
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
|
||||
internalization_candidates: UnordSet<MonoItem<'tcx>>,
|
||||
) {
|
||||
/// For symbol internalization, we need to know whether a symbol/mono-item
|
||||
/// is used from outside the codegen unit it is defined in. This type is
|
||||
@ -522,7 +526,7 @@ fn internalize_symbols<'tcx>(
|
||||
MultipleCgus,
|
||||
}
|
||||
|
||||
let mut mono_item_placements = FxHashMap::default();
|
||||
let mut mono_item_placements = UnordMap::default();
|
||||
let single_codegen_unit = codegen_units.len() == 1;
|
||||
|
||||
if !single_codegen_unit {
|
||||
@ -739,7 +743,7 @@ fn mono_item_linkage_and_visibility<'tcx>(
|
||||
(Linkage::External, vis)
|
||||
}
|
||||
|
||||
type CguNameCache = FxHashMap<(DefId, bool), Symbol>;
|
||||
type CguNameCache = UnordMap<(DefId, bool), Symbol>;
|
||||
|
||||
fn static_visibility<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -932,7 +936,7 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
|
||||
//
|
||||
// Also, unreached inlined items won't be counted here. This is fine.
|
||||
|
||||
let mut inlined_items = FxHashSet::default();
|
||||
let mut inlined_items = UnordSet::default();
|
||||
|
||||
let mut root_items = 0;
|
||||
let mut unique_inlined_items = 0;
|
||||
@ -1164,7 +1168,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
|
||||
}
|
||||
|
||||
if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
|
||||
let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
|
||||
let mut item_to_cgus: UnordMap<_, Vec<_>> = Default::default();
|
||||
|
||||
for cgu in codegen_units {
|
||||
for (&mono_item, &data) in cgu.items() {
|
||||
@ -1240,7 +1244,7 @@ fn dump_mono_items_stats<'tcx>(
|
||||
let mut file = BufWriter::new(file);
|
||||
|
||||
// Gather instantiated mono items grouped by def_id
|
||||
let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
|
||||
let mut items_per_def_id: FxIndexMap<_, Vec<_>> = Default::default();
|
||||
for cgu in codegen_units {
|
||||
cgu.items()
|
||||
.keys()
|
||||
|
@ -4,13 +4,16 @@ version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
|
||||
# tidy-alphabetical-start
|
||||
derivative = "2.2.0"
|
||||
rustc_macros = { path = "../rustc_macros", optional = true }
|
||||
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
||||
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
||||
rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
|
||||
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
||||
rustc_macros = { path = "../rustc_macros", optional = true }
|
||||
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
||||
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
|
||||
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[features]
|
||||
default = ["nightly"]
|
||||
|
@ -7,11 +7,11 @@ use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
|
||||
// EAGER RESOLUTION
|
||||
|
||||
/// Resolves ty, region, and const vars to their inferred values or their root vars.
|
||||
pub struct EagerResolver<
|
||||
'a,
|
||||
pub struct EagerResolver<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
|
||||
where
|
||||
Infcx: InferCtxtLike<Interner = I>,
|
||||
I: Interner = <Infcx as InferCtxtLike>::Interner,
|
||||
> {
|
||||
I: Interner,
|
||||
{
|
||||
infcx: &'a Infcx,
|
||||
}
|
||||
|
||||
|
@ -622,8 +622,6 @@ parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allo
|
||||
parse_out_of_range_hex_escape = out of range hex escape
|
||||
.label = must be a character in the range [\x00-\x7f]
|
||||
|
||||
parse_outer_attr_ambiguous = ambiguous outer attributes
|
||||
|
||||
parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
|
||||
|
||||
parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
|
||||
|
@ -495,15 +495,6 @@ pub(crate) struct OuterAttributeNotAllowedOnIfElse {
|
||||
pub attributes: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_outer_attr_ambiguous)]
|
||||
pub(crate) struct AmbiguousOuterAttributes {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sugg: WrapInParentheses,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_missing_in_in_for_loop)]
|
||||
pub(crate) struct MissingInInForLoop {
|
||||
|
@ -7,7 +7,7 @@ use rustc_ast as ast;
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::token::{self, Delimiter};
|
||||
use rustc_errors::{codes::*, Diag, PResult};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_span::{sym, symbol::kw, BytePos, Span};
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
||||
@ -252,9 +252,23 @@ impl<'a> Parser<'a> {
|
||||
maybe_whole!(self, NtMeta, |attr| attr.into_inner());
|
||||
|
||||
let do_parse = |this: &mut Self| {
|
||||
let is_unsafe = this.eat_keyword(kw::Unsafe);
|
||||
let unsafety = if is_unsafe {
|
||||
let unsafe_span = this.prev_token.span;
|
||||
this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
|
||||
this.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
ast::Safety::Unsafe(unsafe_span)
|
||||
} else {
|
||||
ast::Safety::Default
|
||||
};
|
||||
|
||||
let path = this.parse_path(PathStyle::Mod)?;
|
||||
let args = this.parse_attr_args()?;
|
||||
Ok(ast::AttrItem { path, args, tokens: None })
|
||||
if is_unsafe {
|
||||
this.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||
}
|
||||
Ok(ast::AttrItem { unsafety, path, args, tokens: None })
|
||||
};
|
||||
// Attr items don't have attributes
|
||||
if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) }
|
||||
@ -375,10 +389,25 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
let lo = self.token.span;
|
||||
let is_unsafe = self.eat_keyword(kw::Unsafe);
|
||||
let unsafety = if is_unsafe {
|
||||
let unsafe_span = self.prev_token.span;
|
||||
self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
|
||||
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
ast::Safety::Unsafe(unsafe_span)
|
||||
} else {
|
||||
ast::Safety::Default
|
||||
};
|
||||
|
||||
let path = self.parse_path(PathStyle::Mod)?;
|
||||
let kind = self.parse_meta_item_kind()?;
|
||||
if is_unsafe {
|
||||
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||
}
|
||||
let span = lo.to(self.prev_token.span);
|
||||
Ok(ast::MetaItem { path, kind, span })
|
||||
|
||||
Ok(ast::MetaItem { unsafety, path, kind, span })
|
||||
}
|
||||
|
||||
pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
|
||||
|
@ -130,14 +130,14 @@ pub enum AttemptLocalParseRecovery {
|
||||
}
|
||||
|
||||
impl AttemptLocalParseRecovery {
|
||||
pub fn yes(&self) -> bool {
|
||||
pub(super) fn yes(&self) -> bool {
|
||||
match self {
|
||||
AttemptLocalParseRecovery::Yes => true,
|
||||
AttemptLocalParseRecovery::No => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no(&self) -> bool {
|
||||
pub(super) fn no(&self) -> bool {
|
||||
match self {
|
||||
AttemptLocalParseRecovery::Yes => false,
|
||||
AttemptLocalParseRecovery::No => true,
|
||||
@ -891,7 +891,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_suggest_struct_literal(
|
||||
pub(super) fn maybe_suggest_struct_literal(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
s: BlockCheckMode,
|
||||
@ -2459,7 +2459,7 @@ impl<'a> Parser<'a> {
|
||||
/// Handle encountering a symbol in a generic argument list that is not a `,` or `>`. In this
|
||||
/// case, we emit an error and try to suggest enclosing a const argument in braces if it looks
|
||||
/// like the user has forgotten them.
|
||||
pub fn handle_ambiguous_unbraced_const_arg(
|
||||
pub(super) fn handle_ambiguous_unbraced_const_arg(
|
||||
&mut self,
|
||||
args: &mut ThinVec<AngleBracketedArg>,
|
||||
) -> PResult<'a, bool> {
|
||||
@ -2500,7 +2500,7 @@ impl<'a> Parser<'a> {
|
||||
/// - Single-segment paths (i.e. standalone generic const parameters).
|
||||
/// All other expressions that can be parsed will emit an error suggesting the expression be
|
||||
/// wrapped in braces.
|
||||
pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
|
||||
pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let start = self.token.span;
|
||||
let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
|
||||
err.span_label(
|
||||
@ -2559,7 +2559,7 @@ impl<'a> Parser<'a> {
|
||||
Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
|
||||
}
|
||||
|
||||
pub fn recover_const_param_declaration(
|
||||
pub(super) fn recover_const_param_declaration(
|
||||
&mut self,
|
||||
ty_generics: Option<&Generics>,
|
||||
) -> PResult<'a, Option<GenericArg>> {
|
||||
@ -2589,7 +2589,11 @@ impl<'a> Parser<'a> {
|
||||
/// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
|
||||
/// `foo::<{ bar + 3 }>` and `foo::<{ bar - baz }>`, respectively. We only provide a suggestion
|
||||
/// if we think that the resulting expression would be well formed.
|
||||
pub fn recover_const_arg(&mut self, start: Span, mut err: Diag<'a>) -> PResult<'a, GenericArg> {
|
||||
pub(super) fn recover_const_arg(
|
||||
&mut self,
|
||||
start: Span,
|
||||
mut err: Diag<'a>,
|
||||
) -> PResult<'a, GenericArg> {
|
||||
let is_op_or_dot = AssocOp::from_token(&self.token)
|
||||
.and_then(|op| {
|
||||
if let AssocOp::Greater
|
||||
@ -2690,7 +2694,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Creates a dummy const argument, and reports that the expression must be enclosed in braces
|
||||
pub fn dummy_const_arg_needs_braces(&self, mut err: Diag<'a>, span: Span) -> GenericArg {
|
||||
pub(super) fn dummy_const_arg_needs_braces(&self, mut err: Diag<'a>, span: Span) -> GenericArg {
|
||||
err.multipart_suggestion(
|
||||
"expressions must be enclosed in braces to be used as const generic \
|
||||
arguments",
|
||||
@ -2961,7 +2965,7 @@ impl<'a> Parser<'a> {
|
||||
/// * `=====`
|
||||
/// * `<<<<<`
|
||||
///
|
||||
pub fn is_vcs_conflict_marker(
|
||||
pub(super) fn is_vcs_conflict_marker(
|
||||
&mut self,
|
||||
long_kind: &TokenKind,
|
||||
short_kind: &TokenKind,
|
||||
@ -2981,14 +2985,14 @@ impl<'a> Parser<'a> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn recover_vcs_conflict_marker(&mut self) {
|
||||
pub(super) fn recover_vcs_conflict_marker(&mut self) {
|
||||
if let Err(err) = self.err_vcs_conflict_marker() {
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> {
|
||||
pub(crate) fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> {
|
||||
let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt)
|
||||
else {
|
||||
return Ok(());
|
||||
|
@ -328,9 +328,7 @@ impl<'a> Parser<'a> {
|
||||
this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
|
||||
})?;
|
||||
|
||||
self.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
|
||||
let span = lhs_span.to(rhs.span);
|
||||
|
||||
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
||||
lhs = match op {
|
||||
AssocOp::Add
|
||||
| AssocOp::Subtract
|
||||
@ -429,23 +427,11 @@ impl<'a> Parser<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
fn error_ambiguous_outer_attrs(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) {
|
||||
if let Some(attr) = lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer) {
|
||||
self.dcx().emit_err(errors::AmbiguousOuterAttributes {
|
||||
span: attr.span.to(rhs_span),
|
||||
sugg: errors::WrapInParentheses::Expression {
|
||||
left: attr.span.shrink_to_lo(),
|
||||
right: lhs_span.shrink_to_hi(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Possibly translate the current token to an associative operator.
|
||||
/// The method does not advance the current token.
|
||||
///
|
||||
/// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
|
||||
pub fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
|
||||
pub(super) fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
|
||||
let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
|
||||
// When parsing const expressions, stop parsing when encountering `>`.
|
||||
(
|
||||
@ -520,8 +506,7 @@ impl<'a> Parser<'a> {
|
||||
None
|
||||
};
|
||||
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
|
||||
self.error_ambiguous_outer_attrs(&lhs, lhs.span, rhs_span);
|
||||
let span = lhs.span.to(rhs_span);
|
||||
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
|
||||
let limits =
|
||||
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
||||
let range = self.mk_range(Some(lhs), rhs, limits);
|
||||
@ -739,8 +724,7 @@ impl<'a> Parser<'a> {
|
||||
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
|
||||
this.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
|
||||
this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs))
|
||||
this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
|
||||
};
|
||||
|
||||
// Save the state of the parser before parsing type normally, in case there is a
|
||||
@ -1022,7 +1006,11 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
pub(super) fn parse_dot_suffix_expr(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
base: P<Expr>,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
// At this point we've consumed something like `expr.` and `self.token` holds the token
|
||||
// after the dot.
|
||||
match self.token.uninterpolate().kind {
|
||||
@ -3858,6 +3846,16 @@ impl<'a> Parser<'a> {
|
||||
self.mk_expr(span, ExprKind::Err(guar))
|
||||
}
|
||||
|
||||
/// Create expression span ensuring the span of the parent node
|
||||
/// is larger than the span of lhs and rhs, including the attributes.
|
||||
fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
|
||||
lhs.attrs
|
||||
.iter()
|
||||
.find(|a| a.style == AttrStyle::Outer)
|
||||
.map_or(lhs_span, |a| a.span)
|
||||
.to(rhs_span)
|
||||
}
|
||||
|
||||
fn collect_tokens_for_expr(
|
||||
&mut self,
|
||||
attrs: AttrWrapper,
|
||||
|
@ -2265,7 +2265,7 @@ pub(crate) struct FnParseMode {
|
||||
/// to true.
|
||||
/// * The span is from Edition 2015. In particular, you can get a
|
||||
/// 2015 span inside a 2021 crate using macros.
|
||||
pub req_name: ReqName,
|
||||
pub(super) req_name: ReqName,
|
||||
/// If this flag is set to `true`, then plain, semicolon-terminated function
|
||||
/// prototypes are not allowed here.
|
||||
///
|
||||
@ -2284,7 +2284,7 @@ pub(crate) struct FnParseMode {
|
||||
/// This field should only be set to false if the item is inside of a trait
|
||||
/// definition or extern block. Within an impl block or a module, it should
|
||||
/// always be set to true.
|
||||
pub req_body: bool,
|
||||
pub(super) req_body: bool,
|
||||
}
|
||||
|
||||
/// Parsing of functions and methods.
|
||||
|
@ -11,22 +11,21 @@ mod stmt;
|
||||
mod ty;
|
||||
|
||||
use crate::lexer::UnmatchedDelim;
|
||||
pub use attr_wrapper::AttrWrapper;
|
||||
use attr_wrapper::AttrWrapper;
|
||||
pub use diagnostics::AttemptLocalParseRecovery;
|
||||
pub(crate) use expr::ForbiddenLetReason;
|
||||
pub(crate) use item::FnParseMode;
|
||||
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
||||
pub use path::PathStyle;
|
||||
use path::PathStyle;
|
||||
|
||||
use core::fmt;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
|
||||
use rustc_ast::util::case::Case;
|
||||
use rustc_ast::{
|
||||
self as ast, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs, Expr,
|
||||
ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility,
|
||||
self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs,
|
||||
Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility,
|
||||
VisibilityKind, DUMMY_NODE_ID,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
@ -37,7 +36,7 @@ use rustc_session::parse::ParseSess;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use std::ops::Range;
|
||||
use std::{mem, slice};
|
||||
use std::{fmt, mem, slice};
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
||||
@ -146,7 +145,7 @@ pub struct Parser<'a> {
|
||||
/// The current token.
|
||||
pub token: Token,
|
||||
/// The spacing for the current token.
|
||||
pub token_spacing: Spacing,
|
||||
token_spacing: Spacing,
|
||||
/// The previous token.
|
||||
pub prev_token: Token,
|
||||
pub capture_cfg: bool,
|
||||
@ -187,7 +186,7 @@ pub struct Parser<'a> {
|
||||
current_closure: Option<ClosureSpans>,
|
||||
/// Whether the parser is allowed to do recovery.
|
||||
/// This is disabled when parsing macro arguments, see #103534
|
||||
pub recovery: Recovery,
|
||||
recovery: Recovery,
|
||||
}
|
||||
|
||||
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
|
||||
@ -197,10 +196,10 @@ rustc_data_structures::static_assert_size!(Parser<'_>, 264);
|
||||
|
||||
/// Stores span information about a closure.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClosureSpans {
|
||||
pub whole_closure: Span,
|
||||
pub closing_pipe: Span,
|
||||
pub body: Span,
|
||||
struct ClosureSpans {
|
||||
whole_closure: Span,
|
||||
closing_pipe: Span,
|
||||
body: Span,
|
||||
}
|
||||
|
||||
/// Indicates a range of tokens that should be replaced by
|
||||
@ -220,13 +219,13 @@ pub struct ClosureSpans {
|
||||
/// the first macro inner attribute to invoke a proc-macro).
|
||||
/// When create a `TokenStream`, the inner attributes get inserted
|
||||
/// into the proper place in the token stream.
|
||||
pub type ReplaceRange = (Range<u32>, Vec<(FlatToken, Spacing)>);
|
||||
type ReplaceRange = (Range<u32>, Vec<(FlatToken, Spacing)>);
|
||||
|
||||
/// Controls how we capture tokens. Capturing can be expensive,
|
||||
/// so we try to avoid performing capturing in cases where
|
||||
/// we will never need an `AttrTokenStream`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Capturing {
|
||||
enum Capturing {
|
||||
/// We aren't performing any capturing - this is the default mode.
|
||||
No,
|
||||
/// We are capturing tokens
|
||||
@ -374,13 +373,13 @@ pub enum FollowedByType {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Trailing {
|
||||
enum Trailing {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum TokenDescription {
|
||||
pub(super) enum TokenDescription {
|
||||
ReservedIdentifier,
|
||||
Keyword,
|
||||
ReservedKeyword,
|
||||
@ -388,7 +387,7 @@ pub enum TokenDescription {
|
||||
}
|
||||
|
||||
impl TokenDescription {
|
||||
pub fn from_token(token: &Token) -> Option<Self> {
|
||||
pub(super) fn from_token(token: &Token) -> Option<Self> {
|
||||
match token.kind {
|
||||
_ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier),
|
||||
_ if token.is_used_keyword() => Some(TokenDescription::Keyword),
|
||||
@ -502,7 +501,7 @@ impl<'a> Parser<'a> {
|
||||
/// Expect next token to be edible or inedible token. If edible,
|
||||
/// then consume it; if inedible, then return without consuming
|
||||
/// anything. Signal a fatal error if next token is unexpected.
|
||||
pub fn expect_one_of(
|
||||
fn expect_one_of(
|
||||
&mut self,
|
||||
edible: &[TokenKind],
|
||||
inedible: &[TokenKind],
|
||||
@ -572,7 +571,7 @@ impl<'a> Parser<'a> {
|
||||
/// the main purpose of this function is to reduce the cluttering of the suggestions list
|
||||
/// which using the normal eat method could introduce in some cases.
|
||||
#[inline]
|
||||
pub fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
|
||||
fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
|
||||
let is_present = self.check_noexpect(tok);
|
||||
if is_present {
|
||||
self.bump()
|
||||
@ -1262,9 +1261,12 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
self.eat_keyword(kw::Const);
|
||||
let (attrs, blk) = self.parse_inner_attrs_and_block()?;
|
||||
let expr = self.mk_expr(blk.span, ExprKind::Block(blk, None));
|
||||
let blk_span = expr.span;
|
||||
Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(expr), attrs))
|
||||
let anon_const = AnonConst {
|
||||
id: DUMMY_NODE_ID,
|
||||
value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
|
||||
};
|
||||
let blk_span = anon_const.value.span;
|
||||
Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs))
|
||||
}
|
||||
|
||||
/// Parses mutability (`mut` or nothing).
|
||||
@ -1517,7 +1519,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_tokens_no_attrs<R: HasAttrs + HasTokens>(
|
||||
fn collect_tokens_no_attrs<R: HasAttrs + HasTokens>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut Self) -> PResult<'a, R>,
|
||||
) -> PResult<'a, R> {
|
||||
@ -1538,8 +1540,10 @@ impl<'a> Parser<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
// debug view of the parser's token stream, up to `{lookahead}` tokens
|
||||
pub fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ {
|
||||
// Debug view of the parser's token stream, up to `{lookahead}` tokens.
|
||||
// Only used when debugging.
|
||||
#[allow(unused)]
|
||||
pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ {
|
||||
struct DebugParser<'dbg> {
|
||||
parser: &'dbg Parser<'dbg>,
|
||||
lookahead: usize,
|
||||
@ -1615,7 +1619,7 @@ pub(crate) fn make_unclosed_delims_error(
|
||||
/// is then 'parsed' to build up an `AttrTokenStream` with nested
|
||||
/// `AttrTokenTree::Delimited` tokens.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FlatToken {
|
||||
enum FlatToken {
|
||||
/// A token - this holds both delimiter (e.g. '{' and '}')
|
||||
/// and non-delimiter tokens
|
||||
Token(Token),
|
||||
|
@ -21,14 +21,12 @@ impl MutVisitor for ToZzIdentMutVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe add to `expand.rs`.
|
||||
macro_rules! assert_pred {
|
||||
($pred:expr, $predname:expr, $a:expr , $b:expr) => {{
|
||||
let pred_val = $pred;
|
||||
macro_rules! assert_matches_codepattern {
|
||||
($a:expr , $b:expr) => {{
|
||||
let a_val = $a;
|
||||
let b_val = $b;
|
||||
if !(pred_val(&a_val, &b_val)) {
|
||||
panic!("expected args satisfying {}, got {} and {}", $predname, a_val, b_val);
|
||||
if !matches_codepattern(&a_val, &b_val) {
|
||||
panic!("expected args satisfying `matches_codepattern`, got {} and {}", a_val, b_val);
|
||||
}
|
||||
}};
|
||||
}
|
||||
@ -41,9 +39,7 @@ fn ident_transformation() {
|
||||
let mut krate =
|
||||
string_to_crate("#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
|
||||
zz_visitor.visit_crate(&mut krate);
|
||||
assert_pred!(
|
||||
matches_codepattern,
|
||||
"matches_codepattern",
|
||||
assert_matches_codepattern!(
|
||||
print_crate_items(&krate),
|
||||
"#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()
|
||||
);
|
||||
@ -61,9 +57,7 @@ fn ident_transformation_in_defs() {
|
||||
.to_string(),
|
||||
);
|
||||
zz_visitor.visit_crate(&mut krate);
|
||||
assert_pred!(
|
||||
matches_codepattern,
|
||||
"matches_codepattern",
|
||||
assert_matches_codepattern!(
|
||||
print_crate_items(&krate),
|
||||
"macro_rules! zz{(zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+))}".to_string()
|
||||
);
|
||||
|
@ -20,7 +20,7 @@ use tracing::debug;
|
||||
|
||||
/// Specifies how to parse a path.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum PathStyle {
|
||||
pub(super) enum PathStyle {
|
||||
/// In some contexts, notably in expressions, paths with generic arguments are ambiguous
|
||||
/// with something else. For example, in expressions `segment < ....` can be interpreted
|
||||
/// as a comparison and `segment ( ....` can be interpreted as a function call.
|
||||
|
@ -31,7 +31,7 @@ impl<'a> Parser<'a> {
|
||||
/// Parses a statement. This stops just before trailing semicolons on everything but items.
|
||||
/// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
|
||||
// Public for rustfmt usage.
|
||||
pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
|
||||
pub(super) fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
|
||||
Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| {
|
||||
e.emit();
|
||||
self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
|
||||
|
@ -127,7 +127,7 @@ impl<'a> Parser<'a> {
|
||||
/// Parse a type suitable for a field definition.
|
||||
/// The difference from `parse_ty` is that this version
|
||||
/// allows anonymous structs and unions.
|
||||
pub fn parse_ty_for_field_def(&mut self) -> PResult<'a, P<Ty>> {
|
||||
pub(super) fn parse_ty_for_field_def(&mut self) -> PResult<'a, P<Ty>> {
|
||||
if self.can_begin_anon_struct_or_union() {
|
||||
self.parse_anon_struct_or_union()
|
||||
} else {
|
||||
|
@ -25,15 +25,21 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
|
||||
match attr_info {
|
||||
// `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
|
||||
Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
|
||||
check_builtin_attribute(psess, attr, *name, *template)
|
||||
match parse_meta(psess, attr) {
|
||||
Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, *name, *template),
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
|
||||
// All key-value attributes are restricted to meta-item syntax.
|
||||
parse_meta(psess, attr)
|
||||
.map_err(|err| {
|
||||
match parse_meta(psess, attr) {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -42,6 +48,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
|
||||
pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
|
||||
let item = attr.get_normal_item();
|
||||
Ok(MetaItem {
|
||||
unsafety: item.unsafety,
|
||||
span: attr.span,
|
||||
path: item.path.clone(),
|
||||
kind: match &item.args {
|
||||
@ -103,7 +110,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
|
||||
})
|
||||
}
|
||||
|
||||
pub fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
|
||||
fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
|
||||
if let Delimiter::Parenthesis = delim {
|
||||
return;
|
||||
}
|
||||
@ -113,7 +120,7 @@ pub fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter
|
||||
});
|
||||
}
|
||||
|
||||
pub fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
|
||||
pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
|
||||
if let Delimiter::Parenthesis = delim {
|
||||
return;
|
||||
}
|
||||
@ -133,20 +140,6 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_builtin_attribute(
|
||||
psess: &ParseSess,
|
||||
attr: &Attribute,
|
||||
name: Symbol,
|
||||
template: AttributeTemplate,
|
||||
) {
|
||||
match parse_meta(psess, attr) {
|
||||
Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, name, template),
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_builtin_meta_item(
|
||||
psess: &ParseSess,
|
||||
meta: &MetaItem,
|
||||
|
@ -384,6 +384,10 @@ passes_invalid_attr_at_crate_level =
|
||||
passes_invalid_attr_at_crate_level_item =
|
||||
the inner attribute doesn't annotate this {$kind}
|
||||
|
||||
passes_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
|
||||
.suggestion = remove the `unsafe(...)`
|
||||
.note = extraneous unsafe is not allowed in attributes
|
||||
|
||||
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
|
||||
|
||||
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
|
||||
|
@ -10,7 +10,9 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::StashKey;
|
||||
use rustc_errors::{Applicability, DiagCtxt, IntoDiagArg, MultiSpan};
|
||||
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_feature::{
|
||||
is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP,
|
||||
};
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{self as hir};
|
||||
@ -114,6 +116,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
let mut seen = FxHashMap::default();
|
||||
let attrs = self.tcx.hir().attrs(hir_id);
|
||||
for attr in attrs {
|
||||
self.check_unsafe_attr(attr);
|
||||
|
||||
match attr.path().as_slice() {
|
||||
[sym::diagnostic, sym::do_not_recommend] => {
|
||||
self.check_do_not_recommend(attr.span, hir_id, target)
|
||||
@ -308,6 +312,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
true
|
||||
}
|
||||
|
||||
/// Checks if `unsafe()` is applied to an invalid attribute.
|
||||
fn check_unsafe_attr(&self, attr: &Attribute) {
|
||||
if !attr.is_doc_comment() {
|
||||
let attr_item = attr.get_normal_item();
|
||||
if let ast::Safety::Unsafe(unsafe_span) = attr_item.unsafety {
|
||||
if !is_unsafe_attr(attr.name_or_empty()) {
|
||||
self.dcx().emit_err(errors::InvalidAttrUnsafe {
|
||||
span: unsafe_span,
|
||||
name: attr_item.path.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
|
||||
fn check_diagnostic_on_unimplemented(
|
||||
&self,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user