Auto merge of #3656 - RalfJung:rustup, r=RalfJung

Rustup

for `Scalar::from_i128`
This commit is contained in:
bors 2024-06-08 19:44:26 +00:00
commit 989dfb1066
325 changed files with 4410 additions and 3159 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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